在數據庫中,存在通過一張鏈接表來關聯兩張表的情況。鏈接表僅包含連接兩張表形成多對多關系的外鍵,你需要把這兩張多對多關系的表導入到實體框架模型中。
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.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支持無載荷模式,但是在項目中最好不要使用,因為一旦以後要把無載荷改成有載荷模式,實體關系也要隨之改變、程序代碼也要隨之改變,這樣造成很多不必要的麻煩。有一個好的解決辦法是,在項目的一開始就使用有載荷模式,即使我們的表在一開始是無載荷,我們也可以給他加一個隨機的屬性,使之變成有載荷模式。