前言
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 CHECK ADD 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(db.SaveChanges() > 0); 17 }
可以看到,得益於Entity Framework Feature CTP 5對Entity Framework的擴展,使得我們以Code Only模式編程時,幾乎感覺不到Entity Framework的存在,也就是幾乎不用做另外的事情去適應它,這是一件很美好的事情。並且,微軟官方承諾了將把Entity Framework Feature CTP 5的內容納入到.NET Framework的后續版本中,屆時將不再需要另外下載並安裝Entity Framework Feature CTP 5,Entity Framework本身就支持這些特性了。
總結
本文依次使用Entity Framework支持的Database First、Model First和Code Only三種開發模式實現數據的快速訪問。Database First是Entity Framework最早支持,也是最容易上手的一種開發模式,建議初學者選擇該模式入手;Model First模式也即面向領域的編程模式,該模式更能體現面向對象的思想;Code Only模式適合對Entity Framework技術較熟悉的程序員,它能讓你的代碼更整潔、更易維護。
接下來,我將對實體數據模型進行剖析,詳細講解Entity Framework如何實現對象-關系映射這一ORM的核心功能;在此基礎上,給出一種DIY實體數據模型,實現對POCO和多數據庫的支持。