深入了解Entity Framework框架及訪問數據的幾種方式
一、前言
1、Entity Framework概要
Entity Framework是微軟以ADO.NET為基礎所發展出來的對象關系映射(O/R Mapping)解決方案。該框架曾經為.NET Framework的一部分,但Version 6之後從.NET Framework分離出來,可通過NuGet獲取。
Entity Framework利用抽象化數據結構的方式,將每個數據庫對象都轉換成應用程序對象 (Entity),而數據字段都轉換為屬性 (Property),關系則轉換為結合屬性 (Association),讓數據庫的E/R(實體-聯系圖)模型完全的轉成對象模型,讓程序設計師能用最熟悉的編程語言來調用訪問。
2、什麽是ORM
對象-關系映射(Object Relational Mapping,簡稱ORM),用來把對象模型表示的對象映射到基於SQL的關系模型數據庫結構中去。這樣在具體的操作實體對象的時候,就不需要再去和復雜的SQL語句打交道,只需簡單的操作實體對象的屬性和方法。即用操作對象的方式來操作數據庫。
其它ORM框架:Dapper、NHibernate等。
3、Entity Framework使用說明
①、EF是建立在ADO.NET框架之上的,底層使用的是ADO.NET方法和類來執行數據操作,具體如下圖所示:
②、EF支持SQL Server、MySQL、Oracle
③、EF采用約定大於配置的框架原則,能遵守約定就不要去配置。
④、EF開發數據庫的兩種形式先建數據庫或者先建模型。
⑤、EF三種開發模式:
◆ DataBase First (數據庫優先)
如果數據庫已存在,可以使用VS自動生成數據模型以及相關的edmx文件。
使用簡單、方便,適用於數據庫會頻繁修改來滿足新的需求。會出現修改了數據庫在程序中更新EF不起作用等問題。
◆ Model First (模型優先)
如果數據庫未創建,可以在VS中利用Model設計數據庫,通過設計器生成映射信息(edmx文件),並生成數據庫。開發中很少使用。
◆ Code First (代碼優先)(*)
可以通過設計的數據模型自動生成數據庫,也可以通過已存在的數據庫生成數據模型,進行數據庫映射,都沒有edmx文件。
完全控制代碼,即沒有自動生成的模型和上下文代碼。
數據庫由EF幫助生成,當修改模型後,EF使用DB Miguration自動幫助修改數據庫,但也可以禁用Miguration,手動創建(推薦)。
上圖中前三種分別是DataBase First、Model First 和Code First,而第四種也是Code First。
那麽第三個和第四個到底有什麽區別?項目中如何使用?下面將會重點講解。(*)
⑥、EF三種開發模式使用比較,如下圖所示:
|
說明 |
使用 |
Database First (數據庫優先) |
數據庫已存在(生成edmx文件) |
數據庫頻繁改變 |
Model First (模型優先) |
數據庫未存在(生成edmx文件) |
開發中很少使用 |
Code First(代碼優先) |
數據庫存在/未存在(沒有生成edmx文件) |
完全控制代碼 可以禁用數據遷移 手動修改數據庫和實體類 |
二、Entity Framework 訪問數據三種方式
1、DataBase First模式
1.1、創建
①、創建一個應用程序選擇(.NET Framework類庫),選擇“添加” ->“新建項”->點擊“數據”->選擇“ADO.NET 實體數據模型”,具體如下圖所示:
②、選擇模型內容來自“數據庫的EF設計器”,具體如下圖所示:
③、點擊新建連接如圖二所示,選擇數據庫地址、連接方式和數據庫,然後配置數據連接字符串如圖一所示,具體如下圖所示:
④、選擇要映射的“PersonInfo”表,具體如下圖所示:
⑤、創建完模型之後,你會發現Visual Studio自動生成了“Person”實體類和一個“EntityModelContext”數據庫上下文操作類,具體如下圖所示:
1.2、應用
查詢數據,創建控制臺應用程序,通過NuGet包管理器,添加“Entity Framework”引用,然後配置相應的App.config的數據庫連接,創建測試代碼:
static void Main(string[] args) { //實例化數據庫上下文 using (var dbContext=new DemoDBEntities() ) { //使用Lambda表達式查詢數據 var info = dbContext.PersonInfo.Where(i => i.Name == "ZhangSan").ToList(); //使用Linq語句查詢 var info1 = from i in dbContext.PersonInfo where i.ID == 1 select i; //獲取查詢結果 foreach (var item in info) { Console.WriteLine(" Lambda方式的查詢結果:姓名:" + item.Name +" 年齡:"+item.Age); } //foreach (var item in info1) //{ // Console.WriteLine(" Linq 方式的查詢結果:姓名:" + item.Name + " 年齡:" + item.Age); //} Console.ReadLine(); } }
結果如下圖所示:
1.3、說明
Database First是以數據庫為中心的開發方式;
使用這種模式必須要先設計和創建數據庫,然後使用VS在已有數據庫的基礎上創建ADO.NET實體數據模型,然後使用EF訪問和操作數據庫;
如果數據庫表結構發生改變後,只需在模型設計視圖空白處右鍵,選擇“從數據庫更新模型”接著按照向導操作即可完成模型更新;
上面只是演示了一個查詢的小功能,EF的強大機制還需動手實踐和操作。
2、Model First模式
2.1、創建
①、創建一個應用程序選擇(.NET Framework類庫),選擇“添加” ->“新建項”->點擊“數據”->選擇“ADO.NET 實體數據模型”,具體如下圖所示:
②、選擇模型內容來自“空EF設計器模型”,具體如下圖所示:
③、開始設計實體,在空白處右擊,添加實體(UserInfo)和實體的屬性(eg:ID、Name、Age)等 ,具體如下圖所示:
④、實體模型設計完成,接下來要生成數據庫,選擇“根據模型生成數據庫”,具體如下圖所示:
⑤、創建數據庫,填寫相應的數據庫連接屬性,具體如下圖所示:
⑥、EF模型選擇和Visual Studio自動生成DDL文件,具體如下圖所示:
⑦、選擇自動創建的SQL腳本,此時數據已生成,執行腳本生成所需要的表,具體如下圖所示:
⑧、打開數據庫,可以看到創建的數據庫以及表,具體如下圖所示:
2.2、應用
查詢數據,創建控制臺應用程序,通過NuGet包管理器,添加“Entity Framework”引用,然後配置相應的App.config的數據庫連接,創建測試代碼:
static void Main(string[] args) { using (var dbContext = new ModelFirstContainer()) { //添加 UserInfo userModel = new UserInfo(); userModel.Name = "WangWu"; userModel.Age = 18; dbContext.UserInfo.Add(userModel); dbContext.SaveChanges(); //Linq查詢 var list = from i in dbContext.UserInfo where i.Name == "ZhangSan" select i; //Lambda 表達式查詢 var info = dbContext.UserInfo.Where(i => i.Name == "ZhangSan").ToList(); //獲取數據 foreach (var item in list) { Console.WriteLine(" Linq 方式的查詢結果:姓名:" + item.Name + " 年齡:" + item.Age); } foreach (var item in info) { Console.WriteLine(" Lambda方式的查詢結果:姓名:" + item.Name + " 年齡:" + item.Age); } Console.ReadLine(); } }
結果如下圖所示:
2.3、說明
ModelFirst模式是實體模型先行的開發方式;
先設計實體,然後根據實體再去生成數據庫並且進行相應的操作;
使用這種方式的唯一原因就是想體驗視覺實體設計器。
3、Code First模式
文章開始說到的Code First模式有兩種選擇一種是“空CodeFirst模型”,另一種是“來自數據庫的CodeFirst”,具體如下圖所示:
上圖分別對兩種模式進行了描述,那它們到底該如何使用以及區別是什麽?請看下面的例子。
3.1、空Code First模式
1、創建
①、創建一個應用程序選擇(.NET Framework類庫),選擇“添加” ->“新建項”->點擊“數據”->選擇“ADO.NET 實體數據模型”,具體如下圖所示:
②、選擇模型內容來自“空Code First模型”,具體如下圖所示:
③、點擊完成,具體如下圖所示:
通過上圖我們可以看到生成相應的數據庫上下文以及數據庫連接字符串。(可以根據自己的需求進行修改配置以及添加對應的實體)
2、應用
1)、連接配置文件(修改數據庫連接字符串,改成我們要存放數據庫服務器名)
<connectionStrings> <add name="CodeDB" connectionString="data source=.;initial catalog=CodeDB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"
providerName="System.Data.SqlClient" /> </connectionStrings>
2)、代碼示例:
static void Main(string[] args) { using (var dbContext=new CodeDB() ) { UserInfo userModel = new UserInfo(); userModel.Name = "ZhangSan"; dbContext.UserInfo.Add(userModel); dbContext.SaveChanges(); Console.ReadKey(); } }
3)、運行上面代碼,“空Code First模型”,生成的數據庫如下圖所示:
從上圖可以看出:
1、自動生成數據庫CodeDB;
2、數據庫中生成一張叫__MigrationHistory 的表(是用於記錄代碼遷移的歷史記錄,也是代碼遷移模式的開關,後面會聊);
3、數據庫中還創建一張實體類型(UserInfoes的表),包括字段名以及字段類型等信息;
4、利用代碼添加一條數據到UserInfoes的表中。
以上就是通過空Code First模式創建的數據庫以及表(通過代碼實現數據的創建以及表添加)上面的示例操作到這一步都顯示正常,但是我們在實際開發中,
有時需要向數據庫中添加表以及修改表字段和屬性,那現在我們在實體的代碼中添加一個Age字段,具體如下所示:
public class UserInfo { public int Id { get; set; } public string Name { get; set; } //實體中添加Age字段 public string Age { get; set; } }
現在運行程序
程序出現異常,那我們來看看什麽意思“從數據庫創建以來支持CODEDB上下文的模型發生了變化,考慮使用代碼第一遷移來更新數據庫”,
說的就是模型與實際數據庫結構不一致,需要使用 Code First 中的數據遷移功能來解決問題,下面我們就來看看數據遷移。
3、數據遷移的用法
1、什麽情況需要進行數據遷移
在開發中使用空Code First模式,如果涉及到數據表的變更以及字段修改等操作,該如何做呢?當然如果是新項目,刪除數據庫,然後重新生成就行了,
那麽如果是線上的項目,數據庫中已經有數據了,那麽刪除數據庫重新生成就不行了,那麽該如何解決呢?EF Code First提供了一種數據遷移的操作。
2、如何進行數據遷移
● 手動遷移
當模型與實際數據庫結構不一致時,就需要使用數據遷移。數據遷移我們需要掌握三個方法,它們分別是:
1) 在當前項目中啟用數據遷移 Enable-Migrations
2) 添加遷移版本 Add-Migration 版本名稱
3) 更新數據庫 Update-Database
第一步,選擇需要啟用數據遷移的項目,打開“視圖”->“其它窗口”->“程序包管理器控制臺” 或者可以按快捷鍵 Alt+V,E,O,
然後輸入命令:Enable-Migrations,具體如下圖所示:
顯示當前項目中已啟用數據遷移,項目中會多出 Migrations文件夾以及相關代碼(Migrations文件夾主要是數據遷移的信息),具體如下圖所示
第二步由於我們的模型已經發生了改變,所以需要添加一個新的遷移版本,在程序包管理控制臺
執行如下命令:Add-Migration v1.0 ( 其中的v1.0表示版本號,名稱可以自定義),此時再看項目中就會多出一個文件:
第三步通過數據遷移代碼可以看到數據庫是如何進行更新和修改,想要讓數據庫發生改變,為表添加一個Age字段,
還是需要用到第三個命令:Update-Database(執行成功之後,表中就會添加一個 Age字段)
完成以上三個步驟,此時的模型與實際數據庫結構已經一致,再運行程序,程序就不會報錯了。
● 自動遷移
上面我們利用命令方式手動完成數據遷移的,那麽如果我們在實際開發中,每次修改完模型都要這樣更新數據庫嗎?如果表中有數據時,是否會丟失數據?
當然還有一種方式自動遷移,我們需要在項目中啟用Migrations,然後在Configuration類中設置AutomaticMigrationsEnabled設置為true
還需要在DbContext構造函數中寫上這句
Database.SetInitializer(new MigrateDatabaseToLatestVersion<EntityContext, Configuration>("DBConnectionString")),
通過構造函數把數據庫更新為最新,具體如下圖所示:
說明:如果不喜歡自動遷移,可以手工完成這個操作。手工遷移的好處後,可以隨時退回到某個指定的遷移版本。遷移文件也可以進行版本管理有利於團隊開發。
通過使用Code First模式創建出來的數據庫,默認是開啟了數據遷移,如果我們模型進行了修改,那麽就需要在項目中開啟數據遷移,進行模型和數據庫同步。
數據遷移有分為手動遷移和自動遷移,上面已講解,可以根據自己的項目需求進行選擇。
但是在實際開發中進行數據遷移難免會出現一些問題,如果數據庫存有大量數據,遷移過程有可能導致數據丟失,每次更新模型都要進行數據遷移,
給我們開發帶來很多不便,但是還是想用代碼先行模式開發,那麽我就可以使用“來自數據庫的Code First”的方式,默認是關閉數據遷移的,
方便我們隨時修改數據庫以及模型,提高開發效率,推薦使用,請看下面講解。
3.2、來自數據庫的Code First
1、場景
◆ 數據庫已存在並且不想啟用數據庫遷移;
◆ 習慣通過手動修改實體類,手動修改數據庫表結構,來同步數據庫和模型;
◆ 實現代用優先原則。
2、創建
①、創建一個應用程序選擇(.NET Framework類庫),選擇“添加” ->“新建項”->點擊“數據”->選擇“ADO.NET 實體數據模型”,具體如下圖所示:
②、選擇模型內容來自“來自數據庫的Code First”,具體如下圖所示:
③、選擇連接建據庫,填寫相應的數據庫連接屬性,具體如下圖所示:
④、選擇需要的數據庫對象,具體如下圖所示:
⑤、點擊完成,項目中生成相應的數據庫上下文,具體如下圖所示:
3、應用
static void Main(string[] args) { using (var dbContext=new CodeEntity() ) { PersonInfo userModel = new PersonInfo(); userModel.Name = "LiSi"; dbContext.PersonInfo.Add(userModel); dbContext.SaveChanges(); Console.ReadKey(); } }
4、說明
通過上面的示例代碼運行我們可以看到,“來自數據庫的Code First”,我們可以通過手動創建數據庫,手動修改實體,方便我們隨時修改數據庫和實體,
而且還不會生成__MigrationHistory 的表,也不用進行數據遷移,這種方式可以更好地提現Code First的好處。
3.3 、Code First 模式總結
1)Code First模式中,當模型與表結構不一致時,程序會報錯,有兩種方式使模型和表結構一致,一種是手動修改模型代碼和表結構,另一種是使用數據遷移功能。
這兩種方式不是想選哪一個就選哪一個,取決於是否使用了數據遷移 。
2)使用空Code First模型創建的數據庫默認是開啟數據遷移的;
3)使用來自數據庫的Code First模式中的數據庫,默認是關閉數據遷移的。
4)使用來自數據庫的Code First模式,通過手動改寫實體類,手動改數據庫表結構,來同步模型與實際表結構,可以完全自己控制代碼,推薦使用。
三、Entity Framework 總結
Database First:用於數據庫已經存在,可以使用VS自動生成數據模型,已經相關的edmx信息。
Model First:數據庫未創建,可以在VS中利用Model設計數據庫,通過設計器生成映射信息(edmx文件),並自動生成數據庫。
Code First:通過設計的數據模型自動生成數據庫,不需要額外edmx文件,也可通過已存在的數據庫生成數據模型,進行數據庫映射,同樣不需要edmx文件。
優秀是一種習慣,歡迎大家關註學習
深入了解Entity Framework框架及訪問數據的幾種方式