1. Martin Roy
.Net Portfolio
Mroy513@gmail.com
(513)941-2398
2. Library Project Phase 1
Introduction:
Create a Windows Forms front end C# application and a business tier for an n-tier project.
Audience:
Library employees managing Member and Item information
Project Goals:
Build parts of the business tier for a library involving members and items.
Create and test two assemblies.
The first assembly is a class library project containing various interfaces and
base classes.
The second assembly is a class library project containing various entity,
collection, and validation classes used by existing business processes.
Code should follow best practices
Produce a user interface that is intuitive, requiring minimal training for users
while minimizing resource utilization
Include easily maintainable code, form-based field validation, and all required
error handling.
3. Phase 1 – MDI Screen with Member Info
The application runs inside an MDI form. The Member Info screen displays when
application is brought up. It displays the items currently checked out. Librarian can select
one or more checked out items to check in. If the member has less than four items checked
out a check out button will appear. Juvenile members will show two additional fields: Birth
Date and Adult Member ID.
4. Sample Code
public void LoadMemberInfo()
{
memIDTextBox.Text = memID.ToString();
LibraryAccess la = new LibraryAccess();
try
{
Member member = la.GetMember(memID);
JuvenileMember juv = member as JuvenileMember;
if (juv == null)
{
AdultMember adult = member as AdultMember;
if (adult == null)
{
memInfoStatusLabel.Text = "System Error - Try Again";
return;
}
else
{
LoadAdultData(adult);
}
}
else
{
LoadJuvData(juv);
}
LoadCheckOutList();
}
catch (LibraryException ex)
{
memInfoStatusLabel.Text = "Member Id was not found";
ClearForm();
}
catch
{
memInfoStatusLabel.Text = "System Error. Check Member ID and
Try Again";
ClearForm();
}
}
private void LoadAdultData(AdultMember memb)
{
firstNameTextBox.Text = memb.FirstName;
initialTextBox.Text = memb.MiddleInitial;
lastNameTextBox.Text = memb.LastName;
streetTextBox.Text = memb.Street;
cityTextBox.Text = memb.City;
6. {
ItemsDataSet bookList = la.GetCheckedOutBooks(memID);
itemsBindingSource.DataSource = bookList;
if (memIdExpired || bookList.Items.Count > 3)
checkOutButton.Visible = false;
else
checkOutButton.Visible = true;
}
catch
{
memInfoStatusLabel.Text = "System Error Try Again";
}
}
The Member Information screen displays both Juvenile and Adult information. If the
Membership has expired than the expiration date is Highlighted and the Check Out button is
hidden. If the member has 4 items checked out the Check Out button is hidden. The
Librarian can highlight any checked out item and click the Check In Selected to check in books.
There is a separate Check In screen to check in a book without a Member ID.
7. Add Adult, Add Juvenile and Check In Screens
There are basic edits for the fields. All names must begin with a capital letter. State is selected
from a drop down. Zip code must be 5 or 9 numeric characters. Birth date must show member
is less than 18 years old. The Adult Member Id must be numeric and will be validated against
the data base. ISBN and Copy must be numeric and within valid range.
8. Sample Validation Code
public static bool AdultIDValid(string str)
{
int memID;
if (int.TryParse(str, out memID))
{
if (memID > 0 && memID <= 32767)
{
// get from db
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
/// <summary>
/// Validates first name strats with a capital letter and all others
are lower case a-z
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static bool FirstNameValid(string str)
{
if(Regex.IsMatch(str,"^[A-Z][a-z]{0,14}$"))
return true;
else
return false;
}
/// <summary>
/// Validates that the Initial is a capital lettr A-Z or blank
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static bool InitialValid(string str)
{
if (Regex.IsMatch(str, @"^[A-Zs]{0,1}$"))
return true;
else
return false;
}
/// <summary>
9. /// Validates Last name strats with a capital letter and all others
are lower case a-z
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static bool LastNameValid(string str)
{
if (Regex.IsMatch(str, "^[A-Z][a-z]{0,14}$"))
return true;
else
return false;
}
/// <summary>
/// Validates that ISBN is a valid positive integer
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static bool ISBNValid(string str)
{
int isbn;
if (int.TryParse(str, out isbn))
{
if (isbn > 0)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
/// <summary>
/// Validated that Copy Number is a valid positive Short int
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static bool CopyNumValid(string str)
{
short copyNum;
if (short.TryParse(str, out copyNum))
{
if (copyNum > 0 && copyNum <= 32767)
{
return true;
}
else
{
return false;
10. }
}
else
{
return false;
}
}
/// <summary>
/// Validated that Member ID is a valid positive Short int
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static bool MemberIDValid(string str)
{
short memID;
if (short.TryParse(str, out memID))
{
if (memID > 0 && memID <= 32767)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
}
}
11. Library Project Phase 2
Introduction:
Create the data access layer for the library application.
Audience:
Library employees managing Member and Item information
Project Goals:
Build parts Data access Layer
Develop code to call the store procedures.
Return data or throw errors to Business Layer.
Develop Store procedures for all processes
Create Entities classes to pass data between layers.
Member
Adult (derived from member)
Juvenile (derived from member)
Item
ItemsDataSet (holds multiple Items)
Library Exception
12. Sql Examples
The following validates the juvenile data than creates a Juvenile
Member
CREATE proc [dbo].[AddJuvenile]
@firstname varchar(15),
@middleinitial char(1),
@lastname varchar(15),
@adultmemno smallint,
@birthdate datetime,
@member_no smallint output
as
if @firstname = null or @firstname = ''
begin
raiserror('First Name is required', 11,1)
return
end
if @lastname = null or @lastname = ''
begin
raiserror('Last Name is required', 11,1)
return
end
if not exists (select member_no from adult
where member_no = @adultmemno and
datediff(day,getdate(),expr_date) > 0)
begin
raiserror('Invalid Adult Member Number', 12,1)
return
end
if datediff(day,@birthdate,getdate()) > 6575
begin
raiserror('Birthdate is over 17 years not valid for juvenile', 13,1)
return
end
begin tran
insert into member (lastname,firstname,middleinitial)
values (@lastname,@firstname,@middleinitial)
if @@ERROR <> 0
begin
rollback tran
raiserror('System failure. Unable to add member',16,1)
return
end
set @member_no = scope_identity()
insert into juvenile(member_no,adult_member_no,birth_date)
values(@member_no, @adultmemno,@birthdate)
if @@ERROR <> 0
begin
rollback tran
raiserror('System failure. Unable to add juvenile',16,1)
return
end
commit tran
13. The following Proc is used to check in an item
CREATE proc [dbo].[CheckInItem]
@isbn int,
@copy smallint
as
if not exists (select isbn from copy where isbn = @isbn
and copy_no = @copy)
begin
raiserror('Invalid isbn and copy num', 11,1)
return
end
if exists (select isbn from copy where isbn = @isbn
and copy_no = @copy and on_loan = 'N')
begin
raiserror('Item not currently on loan', 12,1)
return
end
begin tran
update copy set on_loan = 'N'
where isbn = @isbn and copy_no = @copy
if @@error <> 0
begin
rollback tran
raiserror('System error - occured in update to copy', 16,1)
return
end
insert into loanhist (isbn,copy_no,out_date,title_no,member_no,due_date,
in_date)
select isbn,copy_no,out_date,title_no,member_no, due_date,
getdate() from loan where isbn = @isbn and copy_no = @copy
if @@error <> 0
begin
rollback tran
raiserror('System error - occured inserting into loanhist', 16,1)
return
end
delete from loan where isbn = @isbn and copy_no = @copy
if @@error <> 0
begin
rollback tran
raiserror('System error - occured deleting record from loan', 16,1)
return
end
commit tran
14. The following proc will retrieve either the juvenile or adult member
CREATE proc [dbo].[GetMemberInfo]
@memno smallint
as
if not exists (select member_no from member where member_no = @memno)
begin
raiserror('Member not found for member number',11,1)
return
end
if exists(select member_no from adult where member_no = @memno)
begin
select m.firstname,m.middleinitial,m.lastname,a.street,a.city,a.state,
a.zip,a.phone_no,a.expr_date,null adult_member_no,null birth_date
from member m
join adult a
on a.member_no = m.member_no
where m.member_no = @memno
if @@error <> 0
begin
raiserror('System error getting adult info',16,1)
return
end
end
else
begin
select m.firstname,m.middleinitial,m.lastname,a.street,a.city,a.state,
a.zip,a.phone_no,a.expr_date,j.adult_member_no,j.birth_date
from member m
join juvenile j
on m.member_no = j.member_no
join adult a
on a.member_no = j.adult_member_no
where m.member_no = @memno
if @@error <> 0
begin
raiserror('System error getting juvenile info',16,1)
return
end
end
15. Sample Access Layer Code
Check in an item throwing an exception if insert failes
/// <summary>
/// Checks in a book using the ISBN and copy num
/// </summary>
/// <param name="isbn"></param>
/// <param name="copy"></param>
/// <returns></returns>
public void CheckInItem(int isbn, short copy)
{
try
{
using (SqlConnection cnn = new SqlConnection(
Properties.Settings.Default.LibraryConnectionString))
{
using (SqlCommand cmd = new SqlCommand("CheckInItem", cnn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@isbn", isbn);
cmd.Parameters.AddWithValue("@copy", copy);
cnn.Open();
int results = cmd.ExecuteNonQuery();
if (results > 0)
{
return;
}
else
{
LibraryException lex = new LibraryException("System error
no rows were updated");
throw lex;
}
}
}
}
catch (SqlException ex)
{
if (ex.Class == 11)
throw new LibraryException(ErrorCodes.ItemNotFound, ex.Message);
else
if (ex.Class == 12)
throw new LibraryException(ErrorCodes.ItemNotOnLoan,
sex.Message);
else
throw new LibraryException(ErrorCodes.CheckInFailed,
16. This procedures gets the member info. It
determins if this is a juvenile or adault
depending on the presence of an adult member ID.
public Member GetMember(short memID)
{
try
{
using (SqlConnection cnn = new SqlConnection(
Properties.Settings.Default.LibraryConnectionString))
{
using (SqlCommand cmd = new SqlCommand("GetMemberInfo", cnn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@memno", memID);
cnn.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
if (rdr.Read())
{
if (rdr["adult_member_no"].ToString() == "")
{
AdultMember amem = new AdultMember();
LoadMember(rdr, amem, memID);
return amem;
}
else
{
JuvenileMember jmem = new JuvenileMember();
LoadMember(rdr, jmem, memID);
return jmem;
}
}
else
{
LibraryException lex = new LibraryException("System
error no rows returned");
throw lex;
}
}
}
}
}
catch (SqlException sqex)
{
if (sqex.Class == 11)
throw new LibraryException(ErrorCodes.NoSuchMember, sqex.Message);
else
throw new LibraryException(ErrorCodes.GenericException,
sqex.Message, sqex);
}
}
Sample Item Entity
17. public class Item
{
private int isbn;
private short copyNumber;
private string title;
private string author;
private short memberNumber;
private DateTime checkoutDate;
private DateTime dueDate;
/// <summary>
///
/// </summary>
/// <param name="Isbn"></param>
/// <param name="copy"></param>
/// <param name="itemtitle"></param>
/// <param name="author"></param>
/// <param name="memberno"></param>
/// <param name="checkoutDate"></param>
/// <param name="dueDate"></param>
public Item(int Isbn, short copy, string itemtitle, string authr, short
memno,
DateTime outDate, DateTime due)
{
isbn = Isbn;
copyNumber = copy;
title = itemtitle;
author = authr;
memberNumber = memno;
checkoutDate = outDate;
dueDate = due;
}
/// <summary>
/// Get Isbn
/// </summary>
public int ISBN
{
get { return isbn; }
}
/// <summary>
/// Get Copy number
/// </summary>
public short CopyNumber
{
get { return copyNumber; }
}
/// <summary>
/// Get title for isbn
/// </summary>
public string Title
{
get { return title; }
}
18. /// <summary>
/// get author for the isbn
/// </summary>
public string Author
{
get { return author; }
}
/// <summary>
/// get member no of member who has item checked out
/// </summary>
public short MemberNumber
{
get { return memberNumber; }
}
/// <summary>
/// Date item was last checked out
/// </summary>
public DateTime CheckoutDate
{
get { return checkoutDate; }
}
/// <summary>
/// date item is due back
/// </summary>
public DateTime DueDate
{
get { return dueDate; }
set { dueDate = value; }
}
}
19. Library Project Phase 3
Introduction:
Replace Windows front-end with Web front-end
Audience:
Library employees managing Member and Item information
Project Goals:
Replace all Windows forms with Web front end
Additional requirements.
New screen to add a new item to inventory
Automatic conversion to an adult Membership if Juvenile is age is 18 or above.
Membership renewal for expired Member IDs
Add Security
Add logon screen
Prevent access to any screen without valid login
20. Member Information Window
The application runs inside a Master Page. The Member Info screen displays when
after a successful login. It displays the items currently checked out. Librarian can select one
or more checked out items to check in. If the member has less than four items checked out a
check out button will appear. Juvenile members will show two additional fields: Birth Date
and Adult Member ID.
New Features added. If member is expired it will transfer to a new window asking the
librarian if they want to renew. Also if Juvenile is over 17 their membership will
automatically be changed to an adult member. A notification of change is sent to librarian.
21. Sample Code
This code will set up the screen with the current user info when
returning from the other screens.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
ClearForm();
}
object newid = Session["NewMemID"];
if(Session["NewMemID"] != null &&
(short)Session["NewMemID"] != 0)
{
MemID = (short)Session["NewMemID"];
txtMemberID.Text = MemID.ToString();
Session["NewMemID"] = (short) 0;
Session["MemID"] = MemID;
LoadMemberInfo();
}
else
{
if (Session["MemID"] != null)
{
if (short.Parse(txtMemberID.Text) == 0)
{
MemID = (short)Session["MemID"];
txtMemberID.Text = MemID.ToString();
LoadMemberInfo();
}
}
}
}
private void LoadMemberInfo()
{
LibraryAccess la = new LibraryAccess();
try
{
Member member = la.GetMember(memID);
JuvenileMember juv = member as JuvenileMember;
if (juv == null)
{
AdultMember adult = member as AdultMember;
if (adult == null)
{
memInfoStatusLabel.Text = "System Error - Try Again";
return;
}
else
24. New Add Item Screen
Librarian can enter the ISBN and click Get Info for ISBN to get
current information about an Item. It will also show the
highest number copy number used. The librarian can add a new
copy by updating the copy no and clicking Add New Item.
To add a new ISBN the librarian must enter all the
information except Synopsis is optional.