34
Martin Roy .Net Portfolio [email protected] (513)941-2398

Martin Roy Portfolio

Embed Size (px)

DESCRIPTION

Library Projects

Citation preview

Page 1: Martin Roy Portfolio

Martin Roy

.Net Portfolio

[email protected]

(513)941-2398

Page 2: Martin Roy Portfolio

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.

Page 3: Martin Roy Portfolio

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.

Page 4: Martin Roy Portfolio

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;

Page 5: Martin Roy Portfolio

zipTextBox.Text = memb.ZipCode; expDateTextBox.Text = memb.ExpirationDate.ToString("d"); TimeSpan ts = DateTime.Now - memb.ExpirationDate; if (ts.Days > 0) { expDateTextBox.BackColor = Color.Yellow; memIdExpired = true; } else { expDateTextBox.BackColor = Color.WhiteSmoke; memIdExpired = false; } stateTextBox.Text = memb.State; phoneTextBox.Text = memb.PhoneNumber; birthDateLable.Hide(); birthDateTextBox.Hide(); adultIDLabel.Hide(); adultIDTextBox.Hide(); }

private void LoadJuvData(JuvenileMember memb) { firstNameTextBox.Text = memb.FirstName; initialTextBox.Text = memb.MiddleInitial; lastNameTextBox.Text = memb.LastName; streetTextBox.Text = memb.Street; cityTextBox.Text = memb.City; zipTextBox.Text = memb.ZipCode; expDateTextBox.Text = memb.ExpirationDate.ToString("d"); TimeSpan ts = DateTime.Now - memb.ExpirationDate; if (ts.Days > 0) { expDateTextBox.BackColor = Color.Yellow; memIdExpired = true; } else { expDateTextBox.BackColor = Color.WhiteSmoke; memIdExpired = false; } stateTextBox.Text = memb.State; phoneTextBox.Text = memb.PhoneNumber; birthDateLable.Show(); birthDateTextBox.Show(); adultIDLabel.Show(); adultIDTextBox.Show(); birthDateTextBox.Text = memb.BirthDate.ToString("d"); adultIDTextBox.Text = memb.AdultMemberID.ToString(); }

public void LoadCheckOutList() { LibraryAccess la = new LibraryAccess(); try

Page 6: Martin Roy Portfolio

{ 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.

Page 7: Martin Roy Portfolio

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.

Page 8: Martin Roy Portfolio

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-Z\s]{0,1}$")) return true; else return false; }

/// <summary>

Page 9: Martin Roy Portfolio

/// 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;

Page 10: Martin Roy Portfolio

} } 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; } } }}

Page 11: Martin Roy Portfolio

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

Page 12: Martin Roy Portfolio

Sql ExamplesThe following validates the juvenile data than creates a Juvenile MemberCREATE proc [dbo].[AddJuvenile] @firstname varchar(15), @middleinitial char(1),

@lastname varchar(15), @adultmemno smallint, @birthdate datetime, @member_no smallint outputasif @firstname = null or @firstname = ''

begin raiserror('First Name is required', 11,1) returnend

if @lastname = null or @lastname = ''begin raiserror('Last Name is required', 11,1) returnend

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) returnend

if datediff(day,@birthdate,getdate()) > 6575begin raiserror('Birthdate is over 17 years not valid for juvenile', 13,1) returnend

begin traninsert 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

endset @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

endcommit tran

Page 13: Martin Roy Portfolio

The following Proc is used to check in an item

CREATE proc [dbo].[CheckInItem] @isbn int,

@copy smallintas

if not exists (select isbn from copy where isbn = @isbn and copy_no = @copy)

begin raiserror('Invalid isbn and copy num', 11,1) returnend

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 tranupdate copy set on_loan = 'N' where isbn = @isbn and copy_no = @copyif @@error <> 0 begin rollback tran

raiserror('System error - occured in update to copy', 16,1) return

endinsert 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

enddelete from loan where isbn = @isbn and copy_no = @copyif @@error <> 0 begin rollback tran

raiserror('System error - occured deleting record from loan', 16,1) return

endcommit tran

Page 14: Martin Roy Portfolio

The following proc will retrieve either the juvenile or adult member

CREATE proc [dbo].[GetMemberInfo] @memno smallintas if not exists (select member_no from member where member_no = @memno)begin raiserror('Member not found for member number',11,1) returnendif 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 endelse 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 endend

Page 15: Martin Roy Portfolio

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,

Page 16: Martin Roy Portfolio

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

Page 17: Martin Roy Portfolio

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; } }

Page 18: Martin Roy Portfolio

/// <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; } }}

Page 19: Martin Roy Portfolio

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

Page 20: Martin Roy Portfolio

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.

Page 21: Martin Roy Portfolio

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

Page 22: Martin Roy Portfolio

{ LoadAdultData(adult); } } else { LoadJuvData(juv); } if ( TextBoxBirthDate.Text != "" ) { DateTime bday = DateTime.Parse(TextBoxBirthDate.Text); TimeSpan ts = DateTime.Now - bday; if ((ts.Days - 5) / 365 > 17) { CreateAdultIDfromJuv(); } } } catch (LibraryException ex) { memInfoStatusLabel.Text = ex.Message; ClearForm(); } catch { memInfoStatusLabel.Text = "System Error. Check Member ID and Try Again"; ClearForm(); }

}

private void LoadAdultData(AdultMember memb) { TextBoxFirstName.Text = memb.FirstName; TextBoxInit.Text = memb.MiddleInitial; TextBoxLastName.Text = memb.LastName; TextBoxStreet.Text = memb.Street; TextBoxCity.Text = memb.City; TextBoxZip.Text = memb.ZipCode; TextBoxExpDate.Text = memb.ExpirationDate.ToString("d"); TimeSpan ts = DateTime.Now - memb.ExpirationDate; if (ts.Days > 0) { if (Session["RenewalRefused"] == null) Response.Redirect("~/Renew.aspx", true); else { if ((bool)Session["RenewalRefused"]) { TextBoxExpDate.BackColor = Color.Yellow; memIdExpired = true; Session["RenewalRefused"] = null; } } }

Page 23: Martin Roy Portfolio

else { Session["RenewalRefused"] = null; TextBoxExpDate.BackColor = Color.WhiteSmoke; memIdExpired = false; } TextBoxState.Text = memb.State; TextBoxPhone.Text = memb.PhoneNumber; LabelBirthDate.Visible = false; TextBoxBirthDate.Text = ""; TextBoxBirthDate.Visible = false; LabelAdultID.Visible= false; TextBoxAdultID.Visible = false;}

private void LoadJuvData(JuvenileMember memb) { TextBoxFirstName.Text = memb.FirstName; TextBoxInit.Text = memb.MiddleInitial; TextBoxLastName.Text = memb.LastName; TextBoxStreet.Text = memb.Street; TextBoxCity.Text = memb.City; TextBoxZip.Text = memb.ZipCode; TextBoxExpDate.Text = memb.ExpirationDate.ToString("d"); TimeSpan ts = DateTime.Now - memb.ExpirationDate; if (ts.Days > 0) { TextBoxExpDate.BackColor = Color.Yellow; memIdExpired = true; } else { TextBoxExpDate.BackColor = Color.WhiteSmoke; memIdExpired = false; } TextBoxState.Text = memb.State; TextBoxPhone.Text = memb.PhoneNumber; LabelBirthDate.Visible = true; TextBoxBirthDate.Text = memb.BirthDate.ToString("d"); TextBoxBirthDate.Visible =true; LabelAdultID.Visible= true; TextBoxAdultID.Visible = true; TextBoxAdultID.Text = memb.AdultMemberID.ToString(); }

Page 24: Martin Roy Portfolio

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.

Page 25: Martin Roy Portfolio

Selected Code for Add Item Screen

protected void ButtonGetInfo_Click(object sender, EventArgs e) { LibraryAccess la = new LibraryAccess(); try { ItemAddInfo itm = la.GetLastCopyItem(short.Parse(TextBoxISBN.Text)); TextBoxCopy.Text = ""; TextBoxTitle.Text = itm.Title; TextBoxAuthor.Text = itm.Author; TextBoxSynopsis.Text = itm.Synopsis; TextBoxTrans.Text = itm.Translation; LabelLastCopy.Text = string.Format("Highest Copy No used {0}", itm.CopyNumber); if (itm.Cover == "HARDBACK" || itm.Cover == "Hardback") { RadioButtonSoft.Checked = false; RadioButtonHard.Checked = true; } else { RadioButtonHard.Checked = false; RadioButtonSoft.Checked = true; } if (itm.Loanable == "Y" || itm.Loanable == "y") { RadioButtonInHouse.Checked = false; RadioButtonLoan.Checked = true; } else { RadioButtonLoan.Checked = false; RadioButtonInHouse.Checked = true; } } catch (LibraryException lex) { TextBoxTitle.Text = ""; TextBoxAuthor.Text = ""; TextBoxSynopsis.Text = ""; TextBoxTrans.Text = ""; LabelLastCopy.Text = ""; RadioButtonHard.Checked = true; RadioButtonLoan.Checked = true; LabelErrorMsg.Text = lex.Message; } catch (Exception ex) { TextBoxTitle.Text = ""; TextBoxAuthor.Text = ""; TextBoxSynopsis.Text = ""; TextBoxTrans.Text = "";

Page 26: Martin Roy Portfolio

LabelLastCopy.Text = ""; RadioButtonHard.Checked = true; RadioButtonLoan.Checked = true; LabelErrorMsg.Text = "System Error " + ex.Message; }

} /// <summary> /// Adds the new Item. If ISBN exist than only a new copy is added /// otherwise it creates a title item and copy row /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void ButtonAddItem_Click(object sender, EventArgs e) { try { LibraryAccess la = new LibraryAccess(); string cover; if(RadioButtonHard.Checked == true) cover = "HARDBACK"; else cover = "SOFTBACK"; string loanable; if(RadioButtonLoan.Checked == true) loanable = "Y"; else loanable = "N"; la.AddNewItem(int.Parse(TextBoxISBN.Text), short.Parse(TextBoxCopy.Text), TextBoxTitle.Text, TextBoxAuthor.Text, TextBoxSynopsis.Text, TextBoxTrans.Text, cover, loanable); LabelErrorMsg.Text = "Item Added"; } catch (LibraryException lex) { LabelErrorMsg.Text = lex.Message; } catch (Exception ex) { LabelErrorMsg.Text = ex.Message; } }}