Entity Framework 實踐系列 —— 搞好關係 - 同事之間(多對多,many-to-many)

單相思(單向一對一) 兩情相悅(雙向一對一) 到 生兒育女(一對多),這是人生的一項使命 —— 成家。

人生還有另一項使命 —— 立業。它不是一個人的事情,也不是兩個人的事情,它需要很多志同道合的人並肩作戰。與你並肩作戰的人叫作同事,同事之間的關係是雙向的,你和他是同事,同時他和你也是同事,你有很多同事,你的同事也有很多同事。這就是“多對多”關係。

再回到博客的應用場景,文章(BlogPost)與分類(Category)之間也是“多對多”有關係:

一篇文章(BlogPost)可以屬於多個分類,一個分類(Category)可以包含多篇文章。

類圖:

BlogPost類的定義:

複製代碼
public class 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 class Category
{
public int ID { get; set; }
public string Title { get; set; }
public virtual ICollection<BlogPost> BlogPosts { get; set; }
}

數據庫表結構及關係:

BlogPost_Category是外鍵表,用於存儲BlogPost與Category的多對多關係。

那我們如何在Entity Framework中定義這種關係呢?請看代碼:

複製代碼
modelBuilder.Entity<BlogPost>()
.HasMany(b
=> b.Categories)
.WithMany(c
=> c.BlogPosts)
.Map
(
m
=>
{
m.MapLeftKey(
"BlogPostID");
m.MapRightKey(
"CategoryID");
m.ToTable(
"BlogPost_Category");
}
);
複製代碼

HasMany表示一篇文章關聯多個分類,WithMany表示這些分類也分別關聯着多篇文章。你有很多同事,你的同事也有很多同事。

ToTable("BlogPost_Category")表示在BlogPost_Category表中找關係。

MapLeftKey("BlogPostID")與MapRightKey("CategoryID")表示BlogPost要通過BlogPostID找到與自己有關係的人的CategoryID,然後再通過這個CategoryID找到這個人。Category與之相反。

應用場景測試

場景一:獲取一篇文章,並同時得到它所屬的分類

LINQ查詢:

public BlogPost GetBlogPost(int blogPostId)
{
return _blogPostRepository.Entities
.Include(p
=> p.Categories)
.FirstOrDefault(p
=> p.ID == blogPostId);
}

測試代碼:

複製代碼
[TestMethod]
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)
);
}
複製代碼

測試結果:

實際執行的SQL:

場景二:獲取一個分類,並得到它所包含的文章

LINQ查詢:

public Category GetCategory(int categoryId)
{
return _categoryRepository.Entities
.Include(c
=> c.BlogPosts)
.FirstOrDefault(c
=> c.ID == categoryId);
}

測試代碼:

複製代碼
[TestMethod]
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)
);
}
複製代碼

測試結果:

實際執行的SQL:

測試通過!

多對多關係看起來複雜,但只要處理好了,一點也不復雜。

就像同事關係,雖然人越來越多,但只要目標一致,齊心協力,相處起來就很簡單。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章