entityframework学习笔记--004-无载荷与有载荷关系

1.无载荷(with NO Payload)的多对多关系建模

在数据库中,存在通过一张链接表来关联两张表的情况。链接表仅包含连接两张表形成多对多关系的外键,你需要把这两张多对多关系的表导入到实体框架模型中。

1.1 假设我们有如下数据关系:

我们有三张表用来存储Album(专辑)、Artist(艺人)、LinkTable(专辑与艺人的关系表)。一张“专辑”可以有多个“艺人”,同时一个“艺人”也可以有多张专辑。

1.2 右键你的项目,使用entityframework的database first创建实体模型。注意把这三张表都选上,当点击“完成”之后,实体框架生成的视图如图4-1

图4-1

1.3 观察图4-1可以发现,Album与Artist之间的关系被映射成了一条多对多的直线,而当初选择的LinkTable表没有出现在视图中。这是因为LinkTable中没有标量属性,也就是说没有载荷。实体框架认为,LinkTable存在的意义就是表示Album与Artist之间的关系的,而上图足以表示他两的关系,所以LinkTable就没有存在的必要了。但是如果LinkTable中有标量属性,实体框架则会为他创建相应的模型,如下一节2.1。

1.4 对上述关系的插入与查询测试。输出如图4-2

 1 using (var context = new ef6recipesEntities())
 2             {
 3 
 4                 // 添加一个拥有两张专辑的艺术家 
 5                 var artist = new Artist { FirstName = "Alan", LastName = "Jackson" };
 6                 var album1 = new Album { AlbumName = "Drive" };
 7                 var album2 = new Album { AlbumName = "Live at Texas Stadium" };
 8                 artist.Albums.Add(album1);
 9                 artist.Albums.Add(album2);
10                 context.Artists.Add(artist);
11 
12                 //添加两个艺术家的专辑
13                 var artist1 = new Artist { FirstName = "Tobby", LastName = "Keith" };
14                 var artist2 = new Artist { FirstName = "Merle", LastName = "Haggard" };
15                 var album = new Album { AlbumName = "Honkytonk University" };
16                 artist1.Albums.Add(album);
17                 artist2.Albums.Add(album);
18                 context.Artists.Add(artist1); 
19                 context.Artists.Add(artist2);
20 
21                 context.SaveChanges();
22             }
23 
24             using (var context = new ef6recipesEntities())
25             {
26                 Console.WriteLine("Artists and their albums...");
27                 var artists = context.Artists;
28                 foreach (var artist in artists)
29                 {
30                     Console.WriteLine("{0} {1}", artist.FirstName, artist.LastName);
31                     foreach (var album in artist.Albums)
32                     {
33                         Console.WriteLine("\t{0}", album.AlbumName);
34                     }
35                 }
36                 Console.WriteLine("\nAlbums and their artists...");
37                 var albums = context.Albums;
38                 foreach (var album in albums)
39                 {
40                     Console.WriteLine("{0}", album.AlbumName);
41                     foreach (var artist in album.Artists)
42                     {
43                         Console.WriteLine("\t{0} {1}", artist.FirstName, artist.LastName);
44                     }
45                 }
46             }
View Code

图4-2

2 有载荷的多对多关系建模

 在数据库中,存在通过一张链接表来关联两张表的情况。链接表除了包含连接两张表形成多对多关系的外键外,还包含一些额外的属性,你需要把这两张多对多关系的表导入到实体框架模型中。

2.1 假设我们有如下关系:

 

一个订单(Order)可以拥有多个订单项(Item),一个订单项(Item)可以属于多个订单(Order),在连接Order、Item实例的关系上有一个Count属性,这个属性被称为一个有效载荷。

2.2 和上节的一样,右键你的项目,使用entityframework的database first创建实体模型。注意把这三张表都选上,当点击“完成”之后,实体框架生成的视图如图4-2-1

图4-2-1

2.3 观察上图可以发现与上节生成的视图有些不同。这次生成的视图好像更符合数据库中标的结构一样。Order与Item之间的多对多关系,被映射成两个一对多的关系,即Order与OrderItem的一对多、Item与OrderItem的一对多。

2.4 对上述关系的插入与查询测试。输出如图4-2-2

 1 using (var context = new ef6recipesEntities1())
 2             {
 3                 var order = new Order
 4                 {
 5                     OrderId = 1,
 6                     OrderDate = new DateTime(2010, 1, 18)
 7                 };
 8                 var item = new Item
 9                 {
10                     SKU = 1729,
11                     Description = "Backpack",
12                     Price = 29.97
13                 };
14                 var oi1 = new OrderItem { Order = order, Item = item, Count = 1 };
15                 item = new Item
16                 {
17                     SKU = 2929,
18                     Description = "Water Filter",
19                     Price = 13.97
20                 };
21                 var oi2 = new OrderItem { Order = order, Item = item, Count = 3 };
22                 item = new Item
23                 {
24                     SKU = 1847,
25                     Description = "Camp Stove",
26                     Price = 43.99
27                 };
28                 var oi3 = new OrderItem { Order = order, Item = item, Count = 1 };
29                 context.OrderItems.Add(oi1);
30                 context.OrderItems.Add(oi2);
31                 context.OrderItems.Add(oi3);
32                 context.SaveChanges();
33             }
34 
35             using (var context = new ef6recipesEntities1())
36             {
37                 foreach (var order in context.Orders)
38                 {
39                     Console.WriteLine("Order # {0}, ordered on {1}",
40                                        order.OrderId.ToString(),
41                                        order.OrderDate.ToShortDateString());
42                     Console.WriteLine("SKU\tDescription\tQty\tPrice");
43                     Console.WriteLine("---\t-----------\t---\t-----");
44                     foreach (var oi in order.OrderItems)
45                     {
46                         Console.WriteLine("{0}\t{1}\t{2}\t{3}", oi.Item.SKU,
47                                            oi.Item.Description, oi.Count.ToString(),
48                                            oi.Item.Price.ToString("C"));
49                     }
50                 }
51             } 
View Code

 

图4-2-2

 

最后,虽然ef支持无载荷模式,但是在项目中最好不要使用,因为一旦以后要把无载荷改成有载荷模式,实体关系也要随之改变、程序代码也要随之改变,这样造成很多不必要的麻烦。有一个好的解决办法是,在项目的一开始就使用有载荷模式,即使我们的表在一开始是无载荷,我们也可以给他加一个随机的属性,使之变成有载荷模式。

posted @ 2016-11-30 18:39  一品码农  阅读(763)  评论(3编辑  收藏  举报