《Entity Framework 6 Recipes》中文翻譯系列 (42) ------ 第八章 POCO之使用POCO

翻譯的初衷以及爲何選擇《Entity Framework 6 Recipes》來學習,請看本系列開篇

第八章 POCO

  對象不該該知道如何保存它們,加載它們或者過濾它們。這是軟件開發中熟悉的口頭禪,特別是在領域驅動設計中。這是一個聰明的作法,若是對象和持久化綁得太緊,以致於不能對領域對象進行單元測試、重構和複用。在ObjectContext上下對象中,實體框架爲模型實體生成的類,高度依賴實體框架管道(Plumbing)。對於一此開發人員來講,這些類對持久化機制知道得太多了。並且,它們與特定的模型和映射關聯太密切。幸虧,咱們還有另外一個選項。html

  實體框架還支持使用你本身建立的類來做爲模型中的實體。術語叫作「普通公共運行時對象」(Plain Old CLR Object),一般被簡單地叫作POCO,這並不意味着你的類普通而老掉牙。它僅僅是說,它不包含特定框架的引用,不須要來至第三方的代碼,不實現任何第三方的專用接口,而且,它不須要別的任何程序集或者命名空間。你能夠實現本身的領域對象,你會看到經過自定義的ObjectContext上下對象使它們適合模型。也就是說,憑藉實體框架強大的能力,你能夠選擇任何架構模式。你一樣也能使用DbContext爲你產生POCO類。數據庫

  本章涵蓋了多個關於POCO的小節。第一節展現POCO最基本的用法,剩下的小節集中在,實體的加載和實體框架使用對象狀態保持同步。架構

  本章故意手工編寫了大量的POCO類,是爲了演示如何運用POCO。若是使用來至微軟ADO.NET開發團隊的T4模板,這些工做都將不復存在。框架

 

8-1  使用POCO

問題ide

  你想在你的項目中使用POCO。函數

解決方案單元測試

  假設你有如圖8-1所示的數據模型。學習

圖8-1. 一個關於客戶和它的訂單的數據庫模型測試

   

   爲了使用POCO類建立基於圖8-1所示的數據庫模型的實體框架模型,請按下面的步驟進行操做:ui

    一、右鍵你的項目,選擇Add(增長) ➤New Item(新建項);

    二、選擇Visual C#條目下的Data(數據)模板下的ADO.NET Entity Data Model(ADO.NET實體數據模型);

    三、選擇Generate from database 從一個已存在的數據庫建立模型;

    四、選擇表order,OrderDetail,Customer和Product,單擊下一步。在生成的模型中,實體Product有一個導航屬性OrderDetails,它是關聯產品的訂單明細。在這裏它不是必要的,所以將其刪除(譯註:實際上,沒有刪除)。完成後的模型如圖8-2所示。

圖8-2. 客戶訂單的模型

    

     五、咱們使用生成的類做爲的咱們實體,默認狀況下,實體框架6生成POCO實體類。 所以,全部的數據庫訪問代碼都在一個單獨的類中,實體被生成爲普通的類。還能夠在實體框架生成實體類以前關閉模型的代碼生成功能,而後手工建立相同的實體類。 在這個版本中,代碼生成策略已經被設置成None.代碼清單8-1展現了咱們模型中的類。

代碼清單8-1. 咱們模型的POCO類

 1  public partial class Customer
 2     {
 3         public Customer()
 4         {
 5             this.Orders = new HashSet<Order>();
 6         }
 7     
 8         public int CustomerId { get; set; }
 9         public string ContactName { get; set; }
10     
11         public virtual ICollection<Order> Orders { get; set; }
12     }
13 
14  public partial class Order
15     {
16         public Order()
17         {
18             this.OrderDetails = new HashSet<OrderDetail>();
19         }
20     
21         public int OrderId { get; set; }
22         public int CustomerId { get; set; }
23         public System.DateTime OrderDate { get; set; }
24     
25         public virtual Customer Customer { get; set; }
26         public virtual ICollection<OrderDetail> OrderDetails { get; set; }
27     }
28 
29 public partial class OrderDetail
30     {
31         public int OrderId { get; set; }
32         public int ProductId { get; set; }
33         public decimal UnitPrice { get; set; }
34         public int Quantity { get; set; }
35     
36         public virtual Order Order { get; set; }
37         public virtual Product Product { get; set; }
38     }
39  public partial class Product
40     {
41         public Product()
42         {
43             this.OrderDetails = new HashSet<OrderDetail>();
44         }
45     
46         public int ProductId { get; set; }
47         public string ProductName { get; set; }
48         public decimal UnitPrice { get; set; }
49     
50         public virtual ICollection<OrderDetail> OrderDetails { get; set; }
51     }

注意,沒有Product到OrdeDetail的關聯,由於咱們在設計器中移除了導航屬性(譯註:實際上,沒有移除)

    六、爲了使用POCO類,實體框架生成了DbContext的派生類。這個類將咱們模型中的每一個實體公佈成ObjectSet<T>類型。 代碼清章8-2演示了,這個類的定義。 

代碼清單8-2. 生成模型時建立的DbContext派生類

 1  public partial class EFRecipesEntities : DbContext
 2     {
 3         public EFRecipesEntities()
 4             : base("name=EFRecipesEntities")
 5         {
 6         }
 7     
 8         protected override void OnModelCreating(DbModelBuilder modelBuilder)
 9         {
10             throw new UnintentionalCodeFirstException();
11         }
12     
13         public DbSet<Customer> Customers { get; set; }
14         public DbSet<Order> Orders { get; set; }
15         public DbSet<OrderDetail> OrderDetails { get; set; }
16         public DbSet<Product> Products { get; set; }
17     }

  這樣就完成了使用生成POCO類的模型,代碼清單8-3演示了從模型中插入和獲取數據

代碼清單8-3. 使用POCO類

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5                 RunExample();
 6         }
 7 
 8         static void RunExample()
 9         {
10             using (var context = new EFRecipesEntities())
11             {
12                 var tea = new Product { ProductName = "Green Tea", UnitPrice = 1.09M };
13                 var coffee = new Product
14                 {
15                     ProductName = "Colombian Coffee",
16                     UnitPrice = 2.15M
17                 };
18                 var customer = new Customer { ContactName = "Karen Marlowe" };
19                 var order1 = new Order { OrderDate = DateTime.Parse("10/06/13") };
20                 order1.OrderDetails.Add(new OrderDetail
21                 {
22                     Product = tea,
23                     Quantity = 4,
24                     UnitPrice = 1.00M
25                 });
26                 order1.OrderDetails.Add(new OrderDetail
27                 {
28                     Product = coffee,
29                     Quantity = 3,
30                     UnitPrice = 2.15M
31                 });
32                 customer.Orders.Add(order1);
33                 context.Customers.Add(customer);
34                 context.SaveChanges();
35             }
36 
37             using (var context = new EFRecipesEntities())
38             {
39                 var query = context.Customers.Include("Orders.OrderDetails.Product");
40                 foreach (var customer in query)
41                 {
42                     Console.WriteLine("Orders for {0}", customer.ContactName);
43                     foreach (var order in customer.Orders)
44                     {
45                         Console.WriteLine("--Order Date: {0}--",
46                                      order.OrderDate.ToShortDateString());
47                         foreach (var detail in order.OrderDetails)
48                         {
49                             Console.WriteLine(
50                                 "\t{0}, {1} units at {2} each, unit discount: {3}",
51                                 detail.Product.ProductName,
52                                 detail.Quantity.ToString(),
53                                 detail.UnitPrice.ToString("C"),
54                                 (detail.Product.UnitPrice - detail.UnitPrice).ToString("C"));
55                         }
56                     }
57                 }
58             }
59             Console.WriteLine("Enter input to exit:");
60             string line = Console.ReadLine();
61             if (line == "exit")
62             {
63                 return;
64             };
65         }
66     }

代碼清單8-3的輸出以下:

Orders for Karen Marlowe
--Order Date: 4/19/2010--
    Green Tea, 4 units at $1.00 each, unit discount: $0.09
    Colombian Coffee, 3 units at $2.15 each, unit discount: $0.00

原理

  生成POCO類,是當前版本實體框架的默認特性。代碼生成策略的屬性值已經被設置爲None。上下文對象也是被單獨生成。因此POCO類中已經沒有了數據訪問代碼。

  若是與模型中實體對應的全部類已經被建立,它們簡單,潔淨。這樣的話就,沒有代碼生成,沒有上下文被生成。爲了實現適合咱們模型和實體的上下文對象,派生至DbContext的一個新類在數據模型生成時就被建立了。這個類還提供了對應每一個實體的,類型爲DbSet<T>的屬性。 默認狀況下,咱們的上下文對象EFRecipesEntities,已經包含了能鏈接數據庫的構造函數代碼。

 

 

 

實體框架交流QQ羣:  458326058,歡迎有興趣的朋友加入一塊兒交流

謝謝你們的持續關注,個人博客地址:http://www.cnblogs.com/VolcanoCloud/

相關文章
相關標籤/搜索