翻譯的初衷以及為什么選擇《Entity Framework 6 Recipes》來學習,請看本系列開篇
7-5 從跟蹤器中獲取實體
問題
你想創建一個擴展方法,從跟蹤器中獲取實體,用於數據保存前執行一些操作。
解決方案
假設你有如圖7-7所示的模型。
圖7-7. 包含實體Technician和ServiceCall的模型
在這個模型中,每個技術員(technician)都有一些業務服務請求(service call),業務服務請求包含聯系人姓名,問題。使用代碼清單7-4,創建一個擴展方法獲取實體狀態為Added、Modifed或者Unchanged的所有實體。
代碼清單7-4. 創建一個擴展方法獲取實體狀態為Added、Modifed或者Unchanged的所有實體
1 public static class Recipe5Program 2 { 3 public static void Run() 4 { 5 using (var context = new Recipe5Context()) 6 { 7 var tech1 = new Technician { Name = "Julie Kerns" }; 8 var tech2 = new Technician { Name = "Robert Allison" }; 9 context.ServiceCalls.Add(new ServiceCall 10 { 11 ContactName = "Robin Rosen", 12 Issue = "Can't get satellite signal.", 13 Technician = tech1 14 }); 15 context.ServiceCalls.Add(new ServiceCall 16 { 17 ContactName = "Phillip Marlowe", 18 Issue = "Channel not available", 19 Technician = tech2 20 }); 21 22 //獲取Added狀態的實體 23 foreach (var tech in 24 context.ChangeTracker.GetEntities<Technician>()) 25 { 26 Console.WriteLine("Technician: {0}", tech.Name); 27 foreach (var call in tech.ServiceCalls) 28 { 29 Console.WriteLine("\tService Call: Contact {0} about {1}", 30 call.ContactName, call.Issue); 31 } 32 } 33 } 34 35 } 36 } 37 public static class ChangeTrackerExtensions 38 { 39 public static IEnumerable<T> GetEntities<T>(this DbChangeTracker tracker) 40 { 41 var entities = tracker 42 .Entries() 43 .Where(entry => entry.State != EntityState.Detached && entry.Entity != null) 44 .Select(entry => entry.Entity).OfType<T>(); 45 return entities; 46 } 47 }
代碼清單7-4的輸出如下:
Technician: Julie Kerns Service Call: Contact Robin Rosen about Can't get satellite signal. Technician: Robert Allison Service Call: Contact Phillip Marlowe about Channel not available
原理
在代碼清單7-4中,我們實現了擴展方法GetEntities<T>(),它獲取上下中狀態為Added,Modified,和Unchanged的所有實體。這是一個常用的方法,因此有理由只實現一次。在實現GetEntities<T>方法中,我們使用LINQ-to Entities過濾Entries<T>()方法的整個集合。這個方法返回所有的非Detached狀態的條目。我們從返回結果集中過濾掉關系以及為null的條目,從剩下的條目中,我們只選擇給定類型的條目。
在許多重要場景中,你需要實現類似GetEntities<T>()方法的方法。比如,在SaveChanges事件中,你想驗證插入、修改或者刪除的實體。
7-6 從命令行生成模型
問題
你想從命令行生成模型。
解決方案
使用edmgen.exe程序,從命令行為一個給定的數據庫生成模型。點擊開始菜單中Microsoft Visual Studio2012下面的Visual Studio 2012 Command Prompt(命令提示),訪問Visual Studio 2012命令提示工具。
微軟的官方文檔為edmgen命令提供了完整的命令行選項說明。 edmgen命令提供了許多有用的命令行選項。例如,下面的命令,會從測試數據庫中的所有表生成一個模型。
edmgen /mode:FullGeneration /project:Test /provider:"System.Data.SqlClient" /c:"server=localhost;integrated security=true;database=Test;"
其它/model選項也是可以使用的。其中有一個在持續構建過程中很有用,它是/mode: ValidateArtifacts。使用該選項,可以生成一個或多個驗證過的層。你可能會使用下面的選項中的一個或是全部/inssdl 或者/incsdl。如果你想驗證映射層,那么模型中三層都必須指定。
在為指定模型層生成文件時,你可以使用/out選項給文件命名。假如,使用 /outcsdl:MyProject.csdl,將創建一個包含概念層定義的文件,文件名為MyProject.csdl。其它層的用法與此相似。
原理
edmgen命令提供了一種便捷的方式來自動構建模型,同時,它在預生成查詢視圖,為每個模型層生成獨立文件方面,是一個很有用的工具。使用edmgen的一個限制是,它不能生成一個基於數據庫表的一個子集合的模型。
使用edmgen命令預生成視圖,對一個應用的性能有極大的幫助。當一個查詢被執行時,實體框架必須構建一系列的視圖,這些視圖用於訪問和查詢數據庫。不使用edmgen實用工具,視圖的生成會在第一次實體框架調用時。 如果數據模型很小的話,第一次的初始化,不會帶來多大的風險。但是,如果數據模型非常大,或者非常復雜時,這樣的性能影響是不能接受的。在這種情況下,我們有足夠的理由來使用edmgen命令行實體工具。
實體框架交流QQ群: 458326058,歡迎有興趣的朋友加入一起交流
謝謝大家的持續關注,我的博客地址:http://www.cnblogs.com/VolcanoCloud/