Entity Framework技術系列之2:三種開發模式實現資料訪問
前言
Entity Framework支援Database First、Model First和Code Only三種開發模式,各模式的開發流程大相徑庭,開發體驗完全不一樣。三種開發模式各有優缺點,對於程式設計師沒有哪種模式最好,只有哪種模式更適合。接下來我將分別使用這三種開發模式實現同一資料庫模型的資料持久化功能。希望通過實踐能幫助你找到更適合你的開發模式。
Database First
Database First開發模式指以資料庫設計為基礎,並根據資料庫自動生成實體資料模型,從而驅動整個開發流程。該模式的好處在於使用簡單,容易入手。
為了降低學習難度,本文的資料庫模型設計得儘量簡單,如下圖所示:
圖1資料庫模型圖
對應的DDL語句如下:
1 --建立表 2 CREATE TABLE [User]( 3 [ID] [uniqueidentifier] NOT NULL, 4 [Name] [nvarchar](40) NOT NULL, 5 PRIMARY KEY CLUSTERED([ID] ASC) ON [PRIMARY]) 6 GO 7 8 CREATE TABLE [Role]( 9 [ID] [uniqueidentifier] NOT NULL, 10 [Name] [nvarchar](40) NOT NULL, 11 PRIMARY KEY CLUSTERED([ID] ASC) ON [PRIMARY]) 12 GO 13 14 CREATE TABLE [UserRole]( 15 [UserID] [uniqueidentifier] NOT NULL, 16 [RoleID] [uniqueidentifier] NOT NULL, 17 PRIMARY KEY CLUSTERED([UserID] ASC, [RoleID] ASC) ON [PRIMARY]) 18 GO 19 20 --建立外來鍵 21 ALTER TABLE [UserRole] WITH CHECKADD CONSTRAINT [FK_UserRole_User] FOREIGN KEY([UserID]) 22 REFERENCES [User] ([ID]) 23 ON DELETE CASCADE 24 GO 25 26 ALTER TABLE [UserRole] WITH CHECK ADD CONSTRAINT [FK_UserRole_Role] FOREIGN KEY([RoleID]) 27 REFERENCES [Role] ([ID]) 28 ON DELETE CASCADE 29 GO
建立名為“DatabaseFirst”的資料庫,並執行以上的DDL語句,就可以建立本示例所需的資料庫物件了。
在Visual Studio解決方案的DatabaseFirst專案中,新增一個名為DatabaseFirst.edmx的ADO.NET實體資料模型,如下圖所示:
圖2新增ADO.NET實體資料模型
點選“新增”按鈕後,進入建立實體資料模型嚮導的選擇模型內容介面,如下圖所示:
圖3選擇從資料庫生成模型
選擇“從資料庫生成”圖示,並點選“下一步”按鈕,進入選擇資料連線介面,如下圖所示:
圖4設定資料連線
指定你的本地資料連線,選擇“是,在連線字串中包括敏感資料”選項,併為實體連線設定名稱為“DatabaseFirst”,點選“下一步”按鈕,進入選擇資料庫物件介面,如下圖所示:
圖5選擇資料庫物件
可供選擇的資料庫物件包括表、檢視和儲存過程。按上圖所示設定後,點選“完成”按鈕,Visual Studio將自動完成從Database到實體資料模型的生成工作。如下圖所示:
圖6由資料庫生成的實體物件模型
至於生成內容的細節,在此就不作說明了,後續會用一整篇文章來深入剖析實體資料模型的方方面面。
至此,實體資料模型的建立算是完成了。在測試專案的應用程式配置檔案中加入資料庫連線配置,如下所示:
1 <?xml version="1.0" encoding="utf-8"?> 2 <configuration> 3 <connectionStrings> 4 <add name="DatabaseFirst" providerName="System.Data.EntityClient" 5 connectionString="provider=System.Data.SqlClient; 6 provider connection string=" 7 Data Source=localhost; 8 User Id=sa; 9 Password=11111111; 10 Initial Catalog=DatabaseFirst; 11 Integrated Security=False; 12 MultipleActiveResultSets=True;"; 13 metadata=res://*/DatabaseFirst.csdl| 14 res://*/DatabaseFirst.ssdl| 15 res://*/DatabaseFirst.msl"/> 16 </connectionStrings> 17 </configuration>
使用該實體資料模型的測試程式碼如下:
1 using Apollo.Blog.EF.Chapter2.DatabaseFirst; 2 … 3 4 using (var db = new DatabaseFirst.DatabaseFirst()) 5 { 6 var role = new Role(); 7 role.ID = Guid.NewGuid(); 8 role.Name = "Administrator"; 9 db.Roles.AddObject(role); 10 11 var user = new User(); 12 user.ID = Guid.NewGuid(); 13 user.Name = "Apollo"; 14 user.Roles.Add(role); 15 db.Users.AddObject(user); 16 17 db.SaveChanges(); 18 }
Model First
Model First開發模式是指從建立實體資料模型入手,並依據模型生成資料庫,從而驅動整個開發流程。該模式也就是業界流行的面向領域的程式設計模式,它的優點在於,程式設計師可以用與設計建模相同的思維來進行程式碼編寫,更符合面向物件的思想。Model First與Database First是互逆的,但最終都是輸出資料庫和實體資料模型。
在Visual Studio解決方案的ModelFirst專案中,新增一個名為ModelFirst.edmx的ADO.NET實體資料模型,如下圖所示:
圖7新增ADO.NET實體資料模型
點選“新增”按鈕後,進入建立實體資料模型嚮導的選擇模型內容介面,如下圖所示:
圖8選擇空模型進行建模
選擇“空模型”,點選“完成”按鈕,,Visual Studio將新建一個空的實體資料模型。如下圖所示:
圖9生成的空模型
工具箱中提供了建模需要的實體、關聯和繼承元素。通過使用這些元素,建立如下的實體資料模型:
圖10手動建模
用XML(文字)編輯器的方式開啟ModelFirst.edmx檔案,可以看到SSDL和MSL部分的對映程式碼是空的,而只產生了CSDL部分的程式碼;與此同時,檢視ModelFirst.Designer.cs檔案,發現實體類和上下文環境類已經建立了。我們只需將SSDL和MSL部分的程式碼產生就大功告成了。
首先,先使用SQL Server Management Studio工具建立一個名為ModelFirst的空資料庫,如下圖所示:
圖11建立資料庫
。然後,在Visual Studio中雙擊ModelFirst.edmx,回到模型關係圖檢視,在檢視的空白處點選滑鼠右鍵,開啟右鍵選單,如下圖所示:
圖12根據模型生成資料庫
選擇“根據模型生成資料庫”選單項,將進入“生成資料庫”嚮導,如下圖所示:
圖13設定資料庫連線
選擇ModelFirst資料連線(如果是第一次使用鈣連線,請使用 “新建連線”按鈕新建一個指向ModelFirst資料庫的連線),並按上圖所示設定後,點選“下一步”按鈕,進入“摘要和設定”介面,如下圖所示:
圖14自動生成的DDL內容
此時,Visual Studio已經自動生成了DDL語句,點選“完成”按鈕,將ModelFirst.edmx.sql檔案加入專案中。此時,再用XML(文字)編輯器的方式開啟ModelFirst.edmx檔案,可以看到SSDL和MSL部分的對映程式碼也已經生成了。對比ModelFirst和DatabaseFirst生成的.edmx檔案和.Designer.cs後臺檔案,會發現兩者內容其實是一樣的。
資料庫物件的生成有兩種方式,一種是在SQL Server Management Studio中執行ModelFirst.edmx.sql;另一種是使用生成的上下文環境類建立:
1 using (var db = new ModelFirst.ModelFirstContainer()) 2 { 3 if (!db.DatabaseExists()) 4 db.CreateDatabase(); 5 }
至此,實體資料模型的建立算是完成了。在測試專案的應用程式配置檔案中加入資料庫連線配置,如下所示:
1 <?xml version="1.0" encoding="utf-8"?> 2 <configuration> 3 <connectionStrings> 4 <add name="ModelFirstContainer" providerName="System.Data.EntityClient" 5 connectionString="provider=System.Data.SqlClient; 6 provider connection string=" 7 Data Source=localhost; 8 User Id=sa; 9 Password=11111111; 10 Initial Catalog=ModelFirst; 11 Integrated Security=False; 12 MultipleActiveResultSets=True;"; 13 metadata=res://*/ModelFirst.csdl| 14 res://*/ModelFirst.ssdl| 15 res://*/ModelFirst.msl"/> 16 </connectionStrings> 17 </configuration>
使用該實體資料模型的測試程式碼如下:
1 using Apollo.Blog.EF.Chapter2.ModelFirst; 2 … 3 4 using (var db = new ModelFirst.ModelFirstContainer()) 5 { 6 var role = new Role(); 7 role.ID = Guid.NewGuid(); 8 role.Name = "Administrator"; 9 db.Roles.AddObject(role); 10 11 var user = new User(); 12 user.ID = Guid.NewGuid(); 13 user.Name = "Apollo"; 14 user.Roles.Add(role); 15 db.Users.AddObject(user); 16 17 db.SaveChanges(); 18 }
Code Only
Code Only開發模式也叫Code First開發模式,指的是程式設計師完全通過手動編碼,就可以使用Entity Framewokr技術來實現資料訪問。該模式的優點在於,支援POCO(Plain Old CLR Objects,簡單傳統CLR物件),程式碼整潔,程式設計師對程式碼的控制也更靈活自如。Code Only模式的程式碼結構如下圖所示:
圖15 Code Only開發模式的程式碼結構
Code Only開發模式需要Entity Framework Feature CTP支援,建議下載並安裝最新的Entity Framework Feature CTP 5。安裝後,Visual Studio解決方案的為CodeOnly專案新增該元件安裝目錄下的EntityFramework.dll庫引用。
接下來在該專案中新增Role和User兩個POCO類。其中,Role.cs主要程式碼如下:
1 public class Role 2 { 3 public Guid ID { get; set; } 4 5 public string Name { get; set; } 6 7 public IList<User> Users { get; set; } 8 }
User.cs主要程式碼如下:
1 public class User 2 { 3 public Guid ID { get; set; } 4 5 public string Name { get; set; } 6 7 public IList<Role> Roles { get; set; } 8 }
然後,建立一個物件上下文環境EntityContext.cs,主要程式碼如下:
1 using System.Data.Entity; 2 … 3 public class EntityContext : DbContext 4 { 5 public EntityContext() : base("CodeOnly") { } 6 7 public DbSet<Role> Roles { get; set; } 8 9 public DbSet<User> Users { get; set; } 10 }
OK,實體資料模型建成了。在測試專案的應用程式配置檔案中加入資料庫連線配置,如下所示:
1 <?xml version="1.0" encoding="utf-8"?> 2 <configuration> 3 <connectionStrings> 4 <add name="CodeOnly" connectionString="data source=YILIN;initial catalog=CodeOnly;persist security info=True;user id=sa;password=11111111" providerName="System.Data.SqlClient"/> 5 </connectionStrings> 6 </configuration>
使用該實體資料模型的測試程式碼如下:
1 using (var db = new EntityContext()) 2 { 3 db.Database.CreateIfNotExists(); 4 5 var role = new Role(); 6 role.ID = Guid.NewGuid(); 7 role.Name = "Administrator"; 8 db.Roles.Add(role); 9 10 var user = new User(); 11 user.ID = Guid.NewGuid(); 12 user.Name = "Apollo"; 13 user.Roles = new List<Role>() { role }; 14 db.Users.Add(user); 15 16 Assert.IsTrue(d