Entity Framework 實(shí)踐系列 —— 搞好關(guān)系 - 同事之間(多對(duì)多,many-to-many)
從 單相思(單向一對(duì)一) 到 兩情相悅(雙向一對(duì)一) 到 生兒育女(一對(duì)多),這是人生的一項(xiàng)使命 —— 成家。
人生還有另一項(xiàng)使命 —— 立業(yè)。它不是一個(gè)人的事情,也不是兩個(gè)人的事情,它需要很多志同道合的人并肩作戰(zhàn)。與你并肩作戰(zhàn)的人叫作同事,同事之間的關(guān)系是雙向的,你和他是同事,同時(shí)他和你也是同事,你有很多同事,你的同事也有很多同事。這就是“多對(duì)多”關(guān)系。
再回到博客的應(yīng)用場景,文章(BlogPost)與分類(Category)之間也是“多對(duì)多”有關(guān)系:
一篇文章(BlogPost)可以屬于多個(gè)分類,一個(gè)分類(Category)可以包含多篇文章。
類圖:

BlogPost類的定義:
{
public int ID { get; set; }
public string Title { get; set; }
public int BlogID { get; set; }
public virtual BlogSite BlogSite { get; set; }
public virtual ICollection<Category> Categories { get; set; }
}
Category類的定義:
{
public int ID { get; set; }
public string Title { get; set; }
public virtual ICollection<BlogPost> BlogPosts { get; set; }
}
數(shù)據(jù)庫表結(jié)構(gòu)及關(guān)系:

BlogPost_Category是外鍵表,用于存儲(chǔ)BlogPost與Category的多對(duì)多關(guān)系。
那我們?nèi)绾卧贓ntity Framework中定義這種關(guān)系呢?請(qǐng)看代碼:
.HasMany(b => b.Categories)
.WithMany(c => c.BlogPosts)
.Map
(
m =>
{
m.MapLeftKey("BlogPostID");
m.MapRightKey("CategoryID");
m.ToTable("BlogPost_Category");
}
);
HasMany表示一篇文章關(guān)聯(lián)多個(gè)分類,WithMany表示這些分類也分別關(guān)聯(lián)著多篇文章。你有很多同事,你的同事也有很多同事。
ToTable("BlogPost_Category")表示在BlogPost_Category表中找關(guān)系。
MapLeftKey("BlogPostID")與MapRightKey("CategoryID")表示BlogPost要通過BlogPostID找到與自己有關(guān)系的人的CategoryID,然后再通過這個(gè)CategoryID找到這個(gè)人。Category與之相反。
應(yīng)用場景測試
場景一:獲取一篇文章,并同時(shí)得到它所屬的分類
LINQ查詢:
{
return _blogPostRepository.Entities
.Include(p => p.Categories)
.FirstOrDefault(p => p.ID == blogPostId);
}
測試代碼:
public void GetBlogPost_Test()
{
var p = _aggBlogSiteService.GetBlogPost(1);
Assert.IsNotNull(p);
Console.WriteLine("BlogPost:" + p.Title);
Console.WriteLine("Categories:");
p.Categories.ToList().ForEach
(
c => Console.WriteLine("Category:" + c.Title)
);
}
測試結(jié)果:

實(shí)際執(zhí)行的SQL:

場景二:獲取一個(gè)分類,并得到它所包含的文章
LINQ查詢:
{
return _categoryRepository.Entities
.Include(c => c.BlogPosts)
.FirstOrDefault(c => c.ID == categoryId);
}
測試代碼:
public void GetCategory_Test()
{
var category = _aggBlogSiteService.GetCategory(1);
Assert.IsNotNull(category);
Console.WriteLine("Category:" + category.Title);
Console.WriteLine("BlogPosts:");
category.BlogPosts.ToList().ForEach
(
p => Console.WriteLine("BlogPost:" + p.Title)
);
}
測試結(jié)果:

實(shí)際執(zhí)行的SQL:

測試通過!
多對(duì)多關(guān)系看起來復(fù)雜,但只要處理好了,一點(diǎn)也不復(fù)雜。
就像同事關(guān)系,雖然人越來越多,但只要目標(biāo)一致,齊心協(xié)力,相處起來就很簡單。
浙公網(wǎng)安備 33010602011771號(hào)