博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
EF多对多关系中如何利用关系表(EF4.1 Many to Many involves junction table details)
阅读量:5949 次
发布时间:2019-06-19

本文共 2948 字,大约阅读时间需要 9 分钟。

请先看dudu的文章

一般的多对多关系数据库表:

Mapping代码:

Code Snippet
  1. modelBuilder.Entity<BlogPost>()
  2.     .HasMany(b => b.Categories)
  3.     .WithMany(c => c.CategoryBlogPosts)
  4.     .Map
  5.     (
  6.         m =>
  7.         {
  8.             m.MapLeftKey("BlogPostID");
  9.             m.MapRightKey("CategoryID");
  10.             m.ToTable("BlogPost_Category");
  11.         }
  12.     );

问题:如果以上满足不了我们的需求,比如我需要再关系表中增加对当前关系的其它信息,比如isactive,只是个举例,实际博客分类中也许并不需要这个字段。那么在CategoryA.CategoryBlogPosts中我想选取IsActive为true的文章就很痛苦了。

根本原因在于这里的多对多映射叫做direct multi to multi直接隐藏了关系表,我自然想到了用两个一对多来实现,本来多对多就是这样来的。

那么映射就变成下面这样了:

Code Snippet
  1. modelBuilder.Entity<BlogPost_Category>()
  2.     .HasKey(it => it.BlogPostId)
  3.     .HasKey(it => it.CategoryId);
  4. modelBuilder.Entity<BlogPost_Category>()
  5.     .HasRequired(it => it.BlogPost)
  6.     .WithMany(it=>it.BlogPostCategories)
  7.     .HasForeignKey(it => it.BlogPostId).WillCascadeOnDelete(false);
  8. modelBuilder.Entity<BlogPost_Category>()
  9.     .HasRequired(it => it.Category)
  10.     .WithMany(c => c.BlogPost_Categorys)
  11.     .HasForeignKey(it => it.CategoryId).WillCascadeOnDelete(false);

这里修改了之间关联的属性:

Code Snippet
  1. public virtual ICollection<BlogPost_Category> BlogPostCategories { get; set; }
  2.  
  3. public virtual IEnumerable<Category> Categories
  4. {
  5.     get { return BlogPostCategories.Where(it => it.IsActive == true).Select(it => it.Category); }
  6. }
Code Snippet
  1. public virtual ICollection<BlogPost_Category> BlogPost_Categorys { get; set; }
  2.  
  3. public virtual IEnumerable<BlogPost> CategoryBlogPosts
  4. {
  5.     get
  6.     {
  7.         return BlogPost_Categorys
  8.             .Where(it => it.IsActive == true)
  9.             .Select(it => it.BlogPost);
  10.     }
  11. }

测试代码:

Code Snippet
  1. [TestMethod]
  2. public void GetBlogPostsActivedInCategory_Test()
  3. {
  4.     var cat = _aggBlogSiteService.GetCategory(2);
  5.     cat.CategoryBlogPosts.
  6.         ToList()
  7.         .ForEach(p =>
  8.                 {
  9.                     Console.WriteLine(string.Format("ID:{
    0}\tTitle:{
    1}", p.ID,
  10.                                                     p.Title));
  11.                     p.Categories.ToList().ForEach(c => Console.WriteLine(
  12.                         string.Format("Categories:\ttitle:{
    0}\tisActive:{
    1}"
  13.                                       , c.Title
  14.                                       , c.BlogPost_Categorys
  15.                                             .Single(pc => pc.BlogPostId == p.ID && pc.CategoryId == c.ID).IsActive)));
  16.                 });
  17. }

测试数据:

结果测试编译不通过,查了下资料,原来当BlogPostID和CategoryID一起做主键时就无法再作为外键,感觉没道理啊,相信将来Ef会改进,原因也不清楚,有时间得好好研究,另外推荐一本书:

可惜我是忠实的CodeFirst Fans,等下个版本了。

新建另一个键当主键,不过显然是多余的,无所谓了(第三幅图中的ID就此由来~)。

测试结果:

最重要的是SQL脚本:

 
N'SELECT
[Project2].[ID]  [ID],
[Project2].[Title]  [Title],
[Project2].[C1]  [C1],
[Project2].[ID1]  [ID1],
[Project2].[BlogPostId]  [BlogPostId],
[Project2].[CategoryId]  [CategoryId],
[Project2].[IsActive]  [IsActive]
(
[Limit1].[ID]  [ID],
[Limit1].[Title]  [Title],
[Extent2].[ID]  [ID1],
[Extent2].[BlogPostId]  [BlogPostId],
[Extent2].[CategoryId]  [CategoryId],
[Extent2].[IsActive]  [IsActive],
([Extent2].[ID]  )  (  )  1   [C1]
(  (1)
[Extent1].[ID]  [ID],
[Extent1].[Title]  [Title]
[dbo].[Category]  [Extent1]
[Extent1].[ID] = @p__linq__0 )  [Limit1]
[dbo].[BlogPost_Category]  [Extent2]  [Limit1].[ID] = [Extent2].[CategoryId]
)  [Project2]
[Project2].[ID] , [Project2].[C1] ',N'@p__linq__0 ',@p__linq__0=2

呵呵,跟dudu的一样。。。Done

转载于:https://www.cnblogs.com/jinzhao/archive/2011/07/19/EF4-1-Many-to-Many-involves-junction-table-details.html

你可能感兴趣的文章
从前后端分离到GraphQL,携程如何用Node实现?\n
查看>>
JavaScript标准库系列——RegExp对象(三)
查看>>
Linux Namespace系列(09):利用Namespace创建一个简单可用的容器
查看>>
oracle中create table with as和insert into with as语句
查看>>
kafka连接异常
查看>>
11g废弃的Hint - BYPASS_UJVC
查看>>
为什么工业控制系统需要安全防护?
查看>>
Mongodb部署记录[3]-主从搭建
查看>>
hive sql操作
查看>>
tomcat 深度优化
查看>>
127 - "Accordian" Patience
查看>>
nginc+memcache
查看>>
php正则匹配utf-8编码的中文汉字
查看>>
MemCache在Windows环境下的搭建及启动
查看>>
linux下crontab实现定时服务详解
查看>>
Numpy中的random模块中的seed方法的作用
查看>>
用java数组模拟登录和注册功能
查看>>
关于jsb中js与c++的相互调用
查看>>
UVA 122 Trees on the level 二叉树 广搜
查看>>
POJ-2251 Dungeon Master
查看>>