下面我們通過建立一個簡單的例子來學習EF框架,直接進入主題吧:
一 、創建實體數據模型
1. 創建一個控制台應用程序,起名為EFDemo
2. 創建一個實體模型
在EFDemo項目上面右擊選擇添加—新建項—在已安裝的選項中選擇數據—ADO.NET實體對象模型,命名為EFStudy
3. 與數據庫連接
第2步執行完畢會彈出向導,選擇“從數據庫生成”,點擊“新建連接…”按鈕,選擇sql server,下略,測試連接成功后,確定返回,注意下方的App.Config會自動生成一個數據庫名+Entities的名字,此名字會成為上下文的類名,建議修改為***+Context,比如PopContext,然后點擊下一步
4. 指定相應的庫表、視圖和存儲過程生成實體
勾選對應的庫表、視圖和存儲過程生成實體,點擊完成即可。
注:可事先在sql server數據庫中使用以下語句建一張簡單的表
CREATE TABLE [dbo].[SysDept](
[ID] [varchar](16) primary key,
[Name] [varchar](64) NOT NULL
)
GO
以上步驟操作完畢后,在項目中新增文件EFStudy.edmx,並以圖形化方式顯示SysDept類
二、增刪改操作
1.新增
因為前面創建的是控制台應用程序,且為了清晰,只引入了一張表,代碼也從簡,直接在Program.cs里面寫
static void Main(string[] args) { //新增 InsertDept(); } private static void InsertDept() { //數據庫表SysDept已經被EF映射為了SysDept類 //此處可直接使用來定義對象 SysDept sysDept = new SysDept(); //為對象設置屬性 sysDept.ID = "1"; sysDept.Name = "煙台**公司"; //EF已經創建了上下文對象,類名為創建實體類型階段指定的PopContext PopContext context = new PopContext(); //將sysDept對象加入到上下文對象,三種方式 //方式一(推薦) context.SysDept.AddObject(sysDept); //方式二 //context.AddToSysDept(sysDept); //方式三 //context.AddObject("SysDept", sysDept); //以上操作后數據變更在內存中,執行以下操作后保存到數據庫 int i=context.SaveChanges(); Console.WriteLine("影響行數:"+i); }
如上所示,將實體對象添加到上下文對象有三種方式,推薦第一種,符合習慣和自然,第二種在庫表比較多的情況下,難以查找,第三種第一個參數采用字符串,易拼寫錯誤且繁瑣
使用sql server 自帶的SQL Server Profiler(開始—》SQL Server 2008-》性能工具,若找不到,說明你安裝的sql server版本是express,開發版和企業版都有該工具),可查看數據庫執行的每條sql,即可以觀察上述程序執行時,EF將程序中對對象的操作轉換為具體的sql語句,對於初期階段理解學習以及后期的多表關聯下性能調優大有益處。
2.刪除
要刪除某條記錄,就要先找到該條記錄,有兩種方式,一是定義一個新對象,通過Context的Attach方法將該對象加入管理,如下面代碼所示,二是在上下文對象中查找,代碼在修改例子中體現
private static void DeleteDept() { //先定義一個新對象並設置主鍵屬性 SysDept sysDept = new SysDept(); sysDept.ID = "1"; //將此對象附加到上下文對象 PopContext context = new PopContext(); context.SysDept.Attach(sysDept); //移除對象,兩種方法 //方法一,推薦 context.SysDept.DeleteObject(sysDept); //context.DeleteObject(sysDept);//方法二 //以上操作后數據變更在內存中,執行以下操作后保存到數據庫 int i = context.SaveChanges(); Console.WriteLine("影響行數:" + i); }
網上查找資料,發現好多是以下兩種方式,可能在早期版本支持,在EF5.0中已過時,context既無Entry方法,也無Remove方法,sysDept.EntityState屬性只讀,不可設置
1.context.Entry(sysDept).State = EntityState.Deleted;//EntityState枚舉值需using System.Data;
2.context.SysDept.Remove(sysDept)
3.修改
要修改某條記錄,就要先找到該條記錄
private static void UpdateDept() { //找到要修改的記錄,查找參數為lamda表達式,看不懂的可補習相關知識 PopContext context = new PopContext(); SysDept sysDept = context.SysDept.FirstOrDefault(dept => dept.ID == "1"); //修改屬性 sysDept.Name = "青島**公司"; //以上操作后數據變更在內存中,執行以下操作后保存到數據庫 int i = context.SaveChanges(); Console.WriteLine("影響行數:" + i); }
這里體現了上文所說查找記錄的第二種方式,事實上,采用這種方式先找到對象,再對對象進行刪除或者修改操作更符合常理。
同刪除類似,EF5.0中已沒有context.Entry(sysDept).State = EntityState.Modified的寫法
4.事務處理
上面說了增、刪、改,程序中常用到的還有事務處理,與do.net處理類似
private static void Transaction() { PopContext context = new PopContext(); IDbTransaction trans = null; try { //打開連接 context.Connection.Open(); //開始事務 trans=context.Connection.BeginTransaction(); //執行操作 //修改一記錄 SysDept sysDept = context.SysDept.FirstOrDefault(dept => dept.ID == "1"); sysDept.Name = "臨沂****公司"; //新增一記錄 sysDept = new SysDept { ID = "2", Name = "菏澤***公司" }; context.SysDept.AddObject(sysDept); //保存到數據庫 int i=context.SaveChanges(); //提交事務 trans.Commit(); Console.WriteLine("已成功執行,影響行數:"+i); } catch (Exception ex) { trans.Rollback(); Console.WriteLine("發生異常,已回滾" + ex.Message); } finally { context.Connection.Close(); } }
上述過程第一次執行正常提交,把sysDept.Name = "臨沂****公司";中“臨沂”改為“日照”,再執行一次,則會因為重復插入主鍵異常退出,查看數據庫會發現,不僅新數據沒插進去,而且在插入數據之前修改的數據也沒有保存到數據庫,從而說明實現了回滾功能。
注意:此處回滾僅對數據庫有效,內存中PopContext對象中的"臨沂****公司"已經被更改了,回滾不會將內存中的數據恢復到事務前狀態。
三、小結
從本節內容就能看出ORM的優點了,在程序中一方面不需要再寫與數據庫對應的的INSERT/DELETE/UPDATE的SQL語句,特別是在表字段比較多的情況下,寫一個比較長的Insert語句,很容易發生錯位、缺失問題,另一方面可以直接實例化對象,獲取或者設置屬性值時,智能提示很友好也很便利。