ADO.NET Entity Framework by Jose A. Blakeley and Michael Pizzo
Library Management System - V1.0
1. Public Library Management System
As Implemented by: James K. Muturi
James.Muturi@setfocus.com
(973)580-2573
2. Introduction:
A database has been created to support the principal functions of a lending library’s day-to-
day operations: adding new members (adult and juvenile) and checking books in and out.
Project Goals:
Phase 1: Windows Front-End application
Design and develop a front end application that satisfies the four basic functionalities
Develop code that is easily maintainable
Provide validation for all required fields
Provide adequate error handling
Provide a UI that is intuitive, requiring minimal training for users while minimizing
resource utilization
Phase 1: Code Samples
Validation of all required fields using Windows Event Model
private void txbJuveFName_Validating(object sender, CancelEventArgs e)
{
if (!BusinessLayer.Validate.FirstName(txbJuveFName.Text))
{
errorProvider1.SetError(txbJuveFName, "Invalid First Name!!");
e.Cancel = true;
}
}
private void txbJuveFName_Validated(object sender, EventArgs e)
{
errorProvider1.SetError(txbJuveFName, string.Empty);
}
(Validation performed according to business rules encapsulated in business layer. Focus
remains on control until a valid entry is made and errors communicated to user.)
3. Enroll Juvenile member Implementation with exception handling
private void btnJuveEnroll_Click(object sender, EventArgs e)
{
try
{
JuvenileMember jm = new JuvenileMember
{
AdultMemberNum = Int16.Parse(txbJuveSponsorNum.Text),
BirthDate = dtpJuveBirthDate.Value,
FirstName = txbJuveFName.Text,
LastName = txbJuveLName.Text,
ExpirationDate = DateTime.Parse(lblAdultExprDate.Text)
};
if (string.IsNullOrEmpty(txbJuveMI.Text))
{
jm.MiddleInitial = null;
}
else
{
jm.MiddleInitial = txbJuveMI.Text.Trim()[0];
}
BusinessLayer bl = new BusinessLayer();
bl.AddMember(jm);
lblJuveExprDate.Text = jm.ExpirationDate.Value.ToShortDateString();
lblJuveMemberNum.Text = jm.MemberNum.ToString();
}
catch (LibraryException ex) { MessageBox.Show(ex.Message); }
catch (Exception ex)
{ MessageBox.Show(“System Error: Exiting the system ”); this.close(); }
}
(Enrolling member, displaying new member# and expiration date, handle and
communicate errors ensuring a robust and user friendly system.)
4. Validation Implementation
public static bool FirstName(string fName)
{
try
{
string pattern = @"^[A-Z]{1}[a-z]{0,14}$";
return Regex.IsMatch(fName, pattern);
} catch (ArgumentException) { return false; }
}
public static bool MemberNumber(string memberNumObj)
{
short memberNum;
if (!short.TryParse(memberNumObj, out memberNum))
{ return false; }
if (memberNum < 1)
{ return false; }
else { return true; }
}
(Robust validation using TryParse (...) where numeric values are expected and Regular
expressions where text is expected)
5.
6. Phase 2: Business and Data Access Tiers
Project Goals:
Phase 2: Business and Data Access Tiers
Design the Business Entity and Data Access Tiers
Develop code that is easily maintainable
Provide adequate error handling
Use database-programming techniques that provide for maximum programming
flexibility while minimizing resource utilization.
Phase2: Code Samples
Enroll Juvenile member (Data Access Layer)
public void AddMember(JuvenileMember member)
{
try
{
short? xMemberNum = 0;
LibraryEntitiesDataContext dc = new LibraryEntitiesDataContext();
dc.AddJuvenileMember(
member.LastName,
member.FirstName,
member.MiddleInitial,
member.AdultMemberNum,
member.BirthDate,
ref xMemberNum);
member.MemberNum = (short)xMemberNum;
}
catch (System.Data.SqlClient.SqlException ex)
{
ErrorCode err = ProcessSQLException(ex);
throw new LibraryException(err, ex.Message, ex);
}
catch (Exception ex)
{ throw new LibraryException(ErrorCode.None, ex.Message, ex); }
}
(Juvenile member enrolled and any exceptions from the Database caught, repackaged and
rethrown. Juvenile member entity updated with new member# from enrollment)
7. Enroll Juvenile member (SQL Stored Procedure)
ALTER PROCEDURE [dbo].[AddJuvenileMember]
-- parameters for the stored procedure
@lastname varchar(15),
@firstname varchar(15),
@middleinitial char(1),
@adult_member_no smallint,
@birth_date datetime,
@member_no smallint output
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
begin try
begin tran
declare @currDate datetime;
declare @juveCutOff datetime
set @currDate = GETDATE();
set @juveCutOff = DATEADD(YYYY,-18,GETDATE());
-- check for empty or nulls in non-nullable parameters
if (@lastname ='' or @lastname is null
or @firstname='' or @firstname is null
or @adult_member_no < 1 or @adult_member_no is null
or @adult_member_no > 32767
or @birth_date is null or @birth_date > GETDATE())
raiserror('Invalid LName,FName,Sponsor Member# or BirthDate',16,10);
-- check that the juvenile is really a juvenile i.e. < 18yrs
if @juveCutOff > @birth_date
raiserror('Juvenile member over 18: ',16,9);
-- check that sponsor member exists and that membership not expired
if not exists (select * from adult where member_no=@adult_member_no and
expr_date > @currDate)
raiserror('Sponsor does not exist or membership is expired. ',16,9);
-- insert into member table
insert dbo.member (lastname,firstname,middleinitial)
values(@lastname,@firstname,@middleinitial);
--get new member number
set @member_no = SCOPE_IDENTITY();
if @@ROWCOUNT <1
raiserror('Failed to add juvenile member',16,10);
-- insert into juvenile table
insert dbo.juvenile(member_no,adult_member_no,birth_date)
values(@member_no,@adult_member_no,@birth_date)
if @@ROWCOUNT <1
raiserror('Failed to add juvenile member',16,10);
commit tran
end try
8. begin catch
-- rollback transaction
if @@TRANCOUNT > 0
rollback tran;
-- variables for holding exception parameters
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
--populate vars
SELECT @ErrorMessage = ERROR_MESSAGE() ,
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
-- Pass error to calling program (Library DAL)
RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
end catch
END
(Stored procedure implements validation checks on the juvenile member to ensure that
integrity of the information in the database is maintained. Any errors are communicated back
to the calling program through exceptions. If successful, returns to the calling program the new
member#)
Interface (Data Access Layer)
public interface IDataAccess
{
void AddBook(Item item, char loanAble);
void AddBookCopy(Item item);
void AddMember(AdultMember member);
void AddMember(JuvenileMember member);
void CheckInItem(int isbn, short copyNum);
void CheckOutItem(short memberID, int isbn, short copyNum);
Member GetMember(int isbn, short copyNum);
Member GetMember(short memberId);
Item GetItem(int isbn, short copyNum);
ItemsDataSet GetItems(short memberID);
void RenewMember(AdultMember member);
void UpgradeMember(JuvenileMember member);
}
(Contract implemented by the Data Access Layer provides for flexibility and
maintainability as implementation and Interface are separate)
9. Business Entities
Me mbe r AdultMe mbe r Ite m
Class Class Class
Member
Fields Fields
Methods
Properties Properties
AdultMember
City Author
ExpirationDate CopyNum
FirstName DueDate
Juve nile Me mbe r
LastName ISBN
Class
MemberNum Member MemberNum
MemberType OutDate
MiddleInitial Fields Title
PhoneNum Methods
Properties
State
Ad ultMemberN … Item
Street
BirthDate
ZipCode
Methods
Methods
JuvenileMember
Member
(Use of LINQ to SQL classes to abstract data provider code allowing for flexibility and
maintainability)
10. Phase 3: Web Application
Project Goals:
Phase 3: Web Application
Design and develop a web front end application that implements the functionalities
required in Phase I and Phase II.
Develop code that is easily maintainable
Provide validation for all required fields
Provide adequate error handling
Provide a UI that is intuitive, requiring minimal training for users while minimizing
resource utilization
Phase3: Code Samples
Custom Validator
protected void CustomValidator1_ServerValidate(object source,
ServerValidateEventArgs args)
{
DateTime xBirthDate;
if (DateTime.TryParse(args.Value, out xBirthDate))
{
if (JMValidate.IsJuvenile(xBirthDate))
{ args.IsValid = true; }
else
{
args.IsValid = false;
errLabel.Text = "Invalid Birth Date: " + args.Value;
}
}
else
{
args.IsValid = false;
errLabel.Text = "Invalid Birth Date: " + args.Value;
}
}
(Custom validator needed as in-built ASP.NET validators insufficient)
11. Enroll Juvenile member
protected void btnJuveEnroll_Click(object sender, EventArgs e)
{
try
{
//build a member object from client input.
JuvenileMember member = new JuvenileMember
{
BirthDate = Convert.ToDateTime(txbBirthdate.Text.Trim()),
AdultMemberID = Int16.Parse(txbSponsorID.Text),
FirstName = txbFName.Text,
LastName = txbLName.Text,
ExpirationDate = Convert.ToDateTime(lblExprDateInfo.Text.Trim())
};
if (string.IsNullOrEmpty(txbMI.Text))
{ member.MiddleInitial = null; }
else { member.MiddleInitial = txbMI.Text.Trim()[0];}
// add a member through appropriate WCF service
using (LibrarySVCClient proxy =
new LibrarySVCClient("WSHttpBinding_ILibrarySVC"))
{
proxy.ClientCredentials.UserName.UserName = "OtherLibrary";
proxy.ClientCredentials.UserName.Password = "Other@Library";
member = proxy.AddJuvenileMember(member);
}
// update web form with new Member# and expiration date
lblMemberIDInfo.Text = member.MemberID.ToString();
lblExprDateJuveInfo.Text =
member.ExpirationDate.Value.ToShortDateString();
ClearMemberInfo();
}
catch (FaultException<LibraryFault> ex)
{ errLabel2.Text = ex.Detail.Message; }
catch (Exception ex)
{ errLabel2.Text = ex.Message; }
finally { txbFName.Focus(); }
}
13. Phase 4: WCF Service
Project Goals:
Phase 4: WCF Service
Due to success of Library system, the aim is to allow interoperability with other systems
thus the need for a service to further abstract the system and expose it more widely.
Create a WCF service that calls into the business layer
Update the UI layer to call the service instead of the business layer
Use WsHttpBinding
Authenticate using ASP.Net membership where member must be in
role=”LibraryPartner”, Username=”OtherLibrary”, Password=”Other@Library”.
Authorize using ASP.Net roles
Provide previous project functionality.
Phase4: Code Samples
Enroll Juvenile Member Implementation (WCF)
public JuvenileMember AddMember(JuvenileMember member)
{
try
{
BusinessLayer bl = new BusinessLayer();
bl.AddMember(member);
return member;
}
catch (LibraryException ex)
{
LibraryFault fault = ConvertLibraryExceptionToLbraryFault(ex);
throw new FaultException<LibraryFault>(fault, fault.Message);
}
catch (Exception)
{
LibraryFault fault = new LibraryFault();
fault.LibraryErrorCode = ErrorCode.None;
fault.Message = "Service Failure: Contact a system administrator";
throw new FaultException<LibraryFault>(fault, fault.Message);
}
}
(Implementation of the ADD Juvenile member functionality in the service layer)
14. Service Contract
[ServiceContract(Namespace="http://www.jm.setfocus.com")]
public interface ILibrarySVC
{
[OperationContract(Name = "AddJuvenileMember")]
[PrincipalPermission(SecurityAction.Demand, Role = "LibraryPartner")]
[FaultContract(typeof(LibraryFault))]
JuvenileMember AddMember(JuvenileMember member);
[OperationContract(Name = "AddAdultMember")]
[PrincipalPermission(SecurityAction.Demand, Role = "LibraryPartner")]
[FaultContract(typeof(LibraryFault))]
AdultMember AddMember(AdultMember member);
( …. .. .. )
[OperationContract]
[PrincipalPermission(SecurityAction.Demand, Role = "LibraryPartner")]
[FaultContract(typeof(LibraryFault))]
void CheckInItem(int isbn, short copyNum);
[OperationContract]
[PrincipalPermission(SecurityAction.Demand, Role = "LibraryPartner")]
[FaultContract(typeof(LibraryFault))]
void CheckOutItem(short memberID, int isbn, short copyNum);
[OperationContract(Name = "GetBorrowerInfo")]
[PrincipalPermission(SecurityAction.Demand, Role = "LibraryPartner")]
[FaultContract(typeof(LibraryFault))]
Member GetInformation(int isbn, short copyNum);
[OperationContract(Name = "GetMemberInfo")]
[PrincipalPermission(SecurityAction.Demand, Role = "LibraryPartner")]
[FaultContract(typeof(LibraryFault))]
Member GetInformation(short memberId);
( .. .. … .. )
[OperationContract]
[PrincipalPermission(SecurityAction.Demand, Role = "LibraryPartner")]
[FaultContract(typeof(LibraryFault))]
AdultMember RenewMember(AdultMember member);
[OperationContract]
[PrincipalPermission(SecurityAction.Demand, Role = "LibraryPartner")]
[FaultContract(typeof(LibraryFault))]
void UpgradeMember(JuvenileMember member);
}
} (Contract describing services exposed by the WCF Host)