本系列的前3篇文章已經向大家介紹了如何使用Entity Framework4(以下簡稱EF4)建立資料庫並進行增刪改查操作,還介紹了預存程序的調用方法。在以前的例子中,我們沒對代碼進行分層,只是簡單的介紹實現各種操作的方式。今天我們就來談談在三層架構中使用EF4 ,想必很多人已經對三層有過瞭解。 當然,三層不一定適合所有應用開發,但分層的思想是值得借鑒的。
本文所有的Web頁面都和以前一樣,不同的是採用了三層架構。我們對應用進行了邏輯分層,各層分別為:介面層(UI),商務邏輯層(BLL)和資料訪問層(DAL)。而在資料互動環境下的實體物件此時將扮演資料訪問層(DAL)和商務邏輯層(BLL)資料轉送的對象(DTO)。在以前,我們可能需要花時間編寫DTO的代碼,而現在EF4能幫我們省去這一部分時間了。
好吧,下面跟隨我的步驟一起完成這個應用。
步驟1.建立資料庫
為可簡單起見,我們在SQL Server中建立一個OrderSystem資料庫,並且建立一個單獨的表UserAccounts,該表的欄位如下,注意將Id作為主鍵,並設定為識別欄位以便自增。
仍然採用預存程序動作表的資料,我們建立的預存程序如下:
1.UserAccounts_SelectAll查詢表中所有資料
CREATE PROCEDURE [dbo].[UserAccounts_SelectAll] AS SET NOCOUNT ON SELECT Id, FirstName, LastName, AuditFields_InsertDate, AuditFields_UpdateDate FROM UserAccounts RETURN
2.UserAccounts_SelectById通過Id查詢單條表資料
CREATE PROCEDURE [dbo].[UserAccounts_SelectById] ( @Id int ) AS SET NOCOUNT ON SELECT Id, FirstName, LastName, AuditFields_InsertDate, AuditFields_UpdateDate FROM UserAccounts WHERE Id = @IdRETURN
3.UserAccounts_Insert插入一條表資料
CREATE PROCEDURE [dbo].[UserAccounts_Insert]( @FirstName nvarchar(50), @LastName nvarchar(50), @AuditFields_InsertDate datetime, @AuditFields_UpdateDate datetime) AS INSERT INTO UserAccounts (FirstName, LastName, AuditFields_InsertDate, AuditFields_UpdateDate) VALUES (@FirstName, @LastName, @AuditFields_InsertDate, @AuditFields_UpdateDate) SELECT CAST(SCOPE_IDENTITY() AS INT) AS Id
4.UserAccounts_Update更新單條表資料
CREATE PROCEDURE [dbo].[UserAccounts_Update]( @Id int, @FirstName nvarchar(50), @LastName nvarchar(50), @AuditFields_UpdateDate datetime) AS SET NOCOUNT ON UPDATE UserAccounts SET FirstName = @FirstName, LastName = @LastName, AuditFields_UpdateDate = @AuditFields_UpdateDate WHERE Id = @Id RETURN
5.UserAccounts_Delete刪除單條表資料
CREATE PROCEDURE [dbo].[UserAccounts_Delete]( @Id int ) AS SET NOCOUNT ON DELETE FROM UserAccounts WHERE Id = @Id RETURN
步驟2.建立資料訪問層
下來在VS 2010中建立一個新的類庫項目,它將作為資料訪問層。
1.開啟VS,選擇檔案->新項目。
2.選擇“C#類庫”項目,將名字改為OrederSystemDAL
3.選中“為項目建立目錄”,將左邊輸入框內容改為“OrderSystem”,點“OK”。
4.添加資料檢視模型,OrderSystemDAL項目上右鍵,選擇Add->New Item..
5.從項目模板中選擇“ADO.NET Entity Data Mode”,將它名字改為“OrderSystemDataModel.edmx”,點“Add”。
6.將會看到視圖資料模型嚮導,選擇“Generate from database”,點“Next”。
7.選擇資料庫連接,我們建立一個新串連,選擇“New connection”,填寫好登陸資訊並選擇OrderSystem資料後,點“OK”,再點“Next”。
8.選擇資料庫物件,選擇剛建立的UserAccounts表和5個預存程序,點“Finish”。
接下來是建立調用這些預存程序的方法了。
9.展開預存程序檔案夾,右擊“UserAccounts_Delete”預存程序,選擇“ Add Function Import”。
10.彈出“Function Import”框後,保持預設參數,點擊“OK”。
11.UserAccounts_Insert預存程序上右擊,由於它將返回新插入的資料的Id,所以我們要將“Returns a Collection Of”的Scalars參數設定為Int32,然後點“OK”。
12.對其他預存程序重複同樣操作,對於SelectAll 和SelectById預存程序,“Returns a Collection Of”中的Entity參數設定為UserAccount,Update預存程序保持預設即可。
實體資料模型就建立好了,下面要在資料訪問層中建立一個類來管理這些預存程序的調用。
13.添加一個新的類檔案,將其名字改為“UserAccountsData.cs”,將類聲明為公用的和靜態。
public static class UserAccountsData
14.給類添加以下方法:
public static int Insert(string firstName, string lastName, DateTime insertDate){ using (OrderSystemEntities db = new OrderSystemEntities()) { return Insert(db, firstName, lastName, insertDate); }} public static int Insert(OrderSystemEntities db, string firstName, string lastName, DateTime insertDate){ return db.UserAccounts_Insert(firstName, lastName, insertDate, insertDate).ElementAt(0).Value;} public static void Update(int id, string firstName, string lastName, DateTime updateDate){ using (OrderSystemEntities db = new OrderSystemEntities()) { Update(db, id, firstName, lastName, updateDate); }} public static void Update(OrderSystemEntities db, int id, string firstName, string lastName, DateTime updateDate){ db.UserAccounts_Update(id, firstName, lastName, updateDate);} public static void Delete(int id){ using (OrderSystemEntities db = new OrderSystemEntities()) { Delete(db, id); }} public static void Delete(OrderSystemEntities db, int id){ db.UserAccounts_Delete(id);} public static UserAccount SelectById(int id){ using (OrderSystemEntities db = new OrderSystemEntities()) { return SelectById(db, id); }} public static UserAccount SelectById(OrderSystemEntities db, int id){ return db.UserAccounts_SelectById(id).ElementAtOrDefault(0);} public static List<UserAccount> SelectAll(){ using (OrderSystemEntities db = new OrderSystemEntities()) { return SelectAll(db); }} public static List<UserAccount> SelectAll(OrderSystemEntities db){ return db.UserAccounts_SelectAll().ToList();}
以上就是我們用來操作UserAccounts表資料的類了。
步驟3.建立商務邏輯層
商務邏輯層是介於介面層和資料訪問層的,它體現了應用的商務邏輯和一些資料驗證規則。
1.添加一個新的C#類庫項目,將它的名字改為“OrderSystemBLL”
2.給該項目添加DAL項目引用和System.Data.Entity引用。
3.將項目中的“Class1.cs”檔案改名為“UserAccountEO”。EO的意思編輯對象(Edit Object),添加EO尾碼是為了將其和資料訪問層的類區分開。
4.添加命名空間。
using System.Collections;using OrderSystemDAL;
5.添加屬性聲明
public int Id { get; set; }public string FirstName { get; set; }public string LastName { get; set; }public DateTime InsertDate { get; set; }public DateTime UpdateDate { get; set; } public string FullName{ get { return LastName + ", " + FirstName; }}
6.添加下面的代碼用來將資料保持到資料庫,該方法根據對象Id是否賦值來判斷是更新還是插入操作,並且還會進行一系列的驗證,如果驗證不通過,則不能進行資料的插入或更新,相關的錯誤還會返回給它的調用者。
public bool Save(ref ArrayList validationErrors){ ValidateSave(ref validationErrors); if (validationErrors.Count == 0) { if (Id == 0) { Id = UserAccountsData.Insert(FirstName, LastName, DateTime.Now); } else { UserAccountsData.Update(Id, FirstName, LastName, DateTime.Now); } return true; } else { return false; }}private void ValidateSave(ref ArrayList validationErrors){ if (FirstName.Trim() == "") { validationErrors.Add("The First Name is required."); } if (LastName.Trim() == "") { validationErrors.Add("The Last Name is required."); }}
7.添加用來刪除資料的方法,如果要進行驗證可以採取如下的方式
public void Delete(ref ArrayList validationErrors){ ValidateDelete(ref validationErrors); if (validationErrors.Count == 0) { UserAccountsData.Delete(Id); }} private void ValidateDelete(ref ArrayList validationErrors){ //Check for referential integrity.}
8.添加用來查詢單條資料的方法
public bool Select(int id){ UserAccount userAccount = UserAccountsData.SelectById(id); if (userAccount != null) { MapData(userAccount); return true; } else { return false; }} internal void MapData(UserAccount userAccount){ Id = userAccount.Id; FirstName = userAccount.FirstName; LastName = userAccount.LastName; InsertDate = userAccount.AuditFields_InsertDate; UpdateDate = userAccount.AuditFields_UpdateDate;}
9.最後是查詢表所有資料的方法
public static List<UserAccountEO> SelectAll(){ List<UserAccountEO> userAccounts= new List<UserAccountEO>(); List<UserAccountEO> userAccountDTOs = UserAccountsData.SelectAll(); foreach (UserAccount userAccountDTO in userAccountDTOs) { UserAccountEO userAccountEO = new UserAccountEO(); userAccountEO.MapData(userAccountDTO); userAccounts.Add(userAccountEO); } return userAccounts;}
步驟4.建立Web表單
下面就是建立資料增刪改查的頁面了,就是我們所說的介面層
1.建立一個ASP.NET Web項目,命名為“OrderSystemUI”。
2.為該項目添加OrderSystemBLL項目的引用。
3.在web.config中添加connectionStrings配置節,代碼如下:
<connectionstrings> <add name="OrderSystemEntities" connectionstring="你的資料庫連接字串" providername="System.Data.EntityClient" /> </connectionstrings>
4.添加一個WebForm,命名為“Users.aspx”。
5.轉到程式碼檢視,在div之間添加如下html代碼
<table><tbody><tr><td colspan="2"><asp :label id="lblErrorLabel" runat="server" text="Please correct the following issues:" forecolor="Red" visible="false"></asp><asp :label id="lblErrorMessages" runat="server" forecolor="Red" visible="false"></asp></td></tr><tr><td>Select A User:</td><td><asp :dropdownlist id="ddlUsers" runat="server" autopostback="True"></asp></td></tr><tr><td>First Name:</td><td><asp :textbox id="txtFirstName" runat="server"></asp></td></tr><tr><td>Last Name:</td><td><asp :textbox id="txtLastName" runat="server"></asp></td></tr><tr><td>Inserted:</td><td><asp :label id="lblInserted" runat="server"></asp></td></tr><tr><td>Updated:</td><td><asp :label id="lblUpdated" runat="server"></asp></td></tr></tbody></table> <asp :button id="btnSave" runat="server" text="Save" /><asp :button id="btnDelete" runat="server" text="Delete" />
轉到設計檢視,可以看到效果如下:
步驟5.將查詢的資料載入到Drop Down List
下面要做的是在頁面載入時,將UserAccounts表的資料載入到Drop Down List,同時可以在Drop Down List中選擇新增資料。
1.雙擊頁面,建立Page_Load時間處理方法。
2.添加命名空間using OrderSystemBLL;。
3.Page_Load處理方法代碼如下:
protected void Page_Load(object sender, EventArgs e){ if (!IsPostBack) { LoadUserDropDownList(); }}
4.添加LoadUserDropDownList方法
private void LoadUserDropDownList(){ ddlUsers.DataSource = UserAccountEO.SelectAll(); ddlUsers.DataTextField = "FullName"; ddlUsers.DataValueField = "Id"; ddlUsers.DataBind(); ddlUsers.Items.Insert(0, new ListItem("Create New User", ""));}
步驟6.插入和更新資料
設計檢視下,雙擊“Save”按鈕,添加點擊事件處理代碼如下:
protected void btnSave_Click(object sender, EventArgs e){ ArrayList validationErrors = new ArrayList(); UserAccountEO userAccount = new UserAccountEO(); if (ddlUsers.SelectedItem.Value != "") { //Updating userAccount.Id = Convert.ToInt32(ddlUsers.SelectedValue); } userAccount.FirstName = txtFirstName.Text; userAccount.LastName = txtLastName.Text; userAccount.Save(ref validationErrors); if (validationErrors.Count > 0) { ShowValidationMessages(validationErrors); } else { //Reload the drop down list LoadUserDropDownList(); //Select the one the user just saved. ddlUsers.Items.FindByValue(userAccount.Id.ToString()).Selected = true; lblErrorLabel.Visible = false; lblErrorMessages.Visible = false; }} private void ShowValidationMessages(ArrayList validationErrors){ if (validationErrors.Count > 0) { lblErrorLabel.Visible = true; lblErrorMessages.Visible = true; lblErrorMessages.Text = "
"; foreach (string message in validationErrors) { lblErrorMessages.Text += message + "
"; } } else { lblErrorLabel.Visible = false; lblErrorMessages.Visible = false; }}
這裡代碼和以前的代碼不同之處是,多了一些驗證的處理。
步驟7.查詢資料
設計檢視下,雙擊下拉框,給它添加SelectedIndexChanged事件處理方法,代碼如下:
txtFirstName.Text = "";txtLastName.Text = "";lblInserted.Text = "";lblUpdated.Text = ""; if (ddlUsers.SelectedValue != ""){ int userAccountId = Convert.ToInt32(ddlUsers.SelectedValue); UserAccountEO userAccount = new UserAccountEO(); if (userAccount.Select(userAccountId)) { txtFirstName.Text = userAccount.FirstName; txtLastName.Text = userAccount.LastName; lblInserted.Text = userAccount.InsertDate.ToString(); lblUpdated.Text = userAccount.UpdateDate.ToString(); }}
步驟8.刪除資料
視圖設計下,雙擊“Delete”按鈕,給它添加點擊事件處理方法,代碼如下:
if (ddlUsers.SelectedItem.Value != ""){ ArrayList validationErrors = new ArrayList(); UserAccountEO userAccount = new UserAccountEO(); userAccount.Id = Convert.ToInt32(ddlUsers.SelectedValue); userAccount.Delete(ref validationErrors); if (validationErrors.Count > 0) { ShowValidationMessages(validationErrors); } else { LoadUserDropDownList(); txtFirstName.Text = ""; txtLastName.Text = ""; lblInserted.Text = ""; lblUpdated.Text = ""; lblErrorLabel.Visible = false; lblErrorMessages.Visible = false; }}
總結
至此,如何在三層架構中使用EF4就像想你介紹完了,它應該能滿足一般應用的要求。在EF4結合VS2010後,我們發現一個最大的好處是DTO對象不再需要我們自己編寫了,加上調用預存程序智能感知的支援,確實非常方便。
專案檔:http://files.cnblogs.com/lloydsheng/OrderSystem4.zip
獨立部落格連結:http://lloydsheng.com/2010/05/aspnet-40-and-entity-framework-4-part-4-3-layered-approach-to-the-entity-framework.html