c# – 使用外键引用映射多对多关系

前端之家收集整理的这篇文章主要介绍了c# – 使用外键引用映射多对多关系前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
对于精通EF的用户来说,这应该是一个简单的问题.

我有以下模式(在我的脑海中)表示表之间的关系应该如何.

  1. [FooBar] [Foo] [Bar]
  2.  
  3. FooId PK,FK Id PK Id PK
  4. BarId PK,FK BarId FK Name
  5. IsRead Name Description
  6. Description

但是,当我尝试使用EF代码生成模式时,首先它无法解释实体之间的关系,因为我已经解释了它们(将外键FooId添加到[bar]表中)并且无法完全创建[FooBar]桥牌桌.

如果有人可以指导我如何使用EF4代码实现上述架构 – 首先我很感激.只要创建了所需的数据库模式,解决方案是否涉及我的POCO模型上的属性,流畅的配置或两者的混合都无关紧要.

POCO型号:

  1. public class Foo
  2. {
  3. public int Id { get; set; }
  4. public string Text { get; set; }
  5. public string Description { get; set; }
  6. public int BarId { get; set; }
  7.  
  8. public Bar Bar { get; set; } /* bar entity */
  9.  
  10. public virtual ICollection<Bar> BridgedBars { get; set; }
  11.  
  12. public Foo()
  13. {
  14. Bars = new List<Bar>();
  15. }
  16. }
  17.  
  18. public class Bar
  19. {
  20. public int Id { get; set; }
  21. public string Text { get; set; }
  22. public string Description { get; set; }
  23.  
  24. public virtual ICollection<Foo> Foos { get; set; }
  25. public virtual ICollection<Foo> BridgedFoos { get; set; }
  26.  
  27. public Bar()
  28. {
  29. Foos = new List<Foo>();
  30. BridgedFoos = new List<Foo>();
  31. }
  32. }
  33.  
  34. public class FooBar
  35. {
  36. public int FooId { get; set; }
  37. public int BarId { get; set; }
  38.  
  39. public virtual Foo Foo { get; set; }
  40. public virtual Bar Bar { get; set; }
  41.  
  42. public bool IsRead { get; set; }
  43. }

解决方法

您的模型确实会在Bar中创建一个外键FooId,它属于Foo.BrideBars定义的关系. EF不将此导航属性与ICollection< Foo>之一相关联. Bar中的属性因为有两个而EF不能唯一确定哪个是正确的对.因此,它为Foo.BrideBars创建了一个关系,而另一端没有导航属性.可以这么说,有一个不可见的Bar.Foo属性导致外键.

要映射到模型的数据库模式实际上并不代表多对多关系,而是与中间“桥”实体FooBar的两个一对多关系.您必须在导航属性中使用此类来定义正确的关系.它看起来像这样:

  1. public class Foo
  2. {
  3. public int Id { get; set; }
  4. public string Text { get; set; }
  5. public string Description { get; set; }
  6.  
  7. public int BarId { get; set; }
  8. public Bar Bar { get; set; }
  9.  
  10. public virtual ICollection<FooBar> FooBars { get; set; }
  11. }
  12.  
  13. public class Bar
  14. {
  15. public int Id { get; set; }
  16. public string Text { get; set; }
  17. public string Description { get; set; }
  18.  
  19. public virtual ICollection<Foo> Foos { get; set; }
  20. public virtual ICollection<FooBar> FooBars { get; set; }
  21.  
  22. }
  23.  
  24. public class FooBar
  25. {
  26. [Key,Column(Order = 0)]
  27. public int FooId { get; set; }
  28. [Key,Column(Order = 1)]
  29. public int BarId { get; set; }
  30.  
  31. public virtual Foo Foo { get; set; }
  32. public virtual Bar Bar { get; set; }
  33.  
  34. public bool IsRead { get; set; }
  35. }

将通过此模型中的命名约定检测正确的关系.仅对于FooBar实体,必须显式定义键,因为属性名称不符合约定(没有Id和没有FooBarId属性).在这个模型中,在FooBar中使用复合键是有意义的.

我想,你的真正的类和属性没有名字Foo和Bar.如果您的真实姓名不遵循惯例,则可能需要指定与注释的关系 – 或使用Fluent API:

  1. modelBuilder.Entity<Foo>()
  2. .Hasrequired(f => f.Bar)
  3. .WithMany(b => b.Foos)
  4. .HasForeignKey(f => f.BarId);
  5.  
  6. modelBuilder.Entity<FooBar>()
  7. .HasKey(fb => new { fb.FooId,fb.BarId }); // replaces the [Key] annotations
  8.  
  9. modelBuilder.Entity<FooBar>()
  10. .Hasrequired(fb => fb.Foo)
  11. .WithMany(f => f.FooBars)
  12. .HasForeignKey(fb => fb.FooId);
  13.  
  14. modelBuilder.Entity<FooBar>()
  15. .Hasrequired(fb => fb.Bar)
  16. .WithMany(b => b.FooBars)
  17. .HasForeignKey(fb => fb.BarId);

在您的数据库模式中,FooBar表将具有复合主键:

  1. [FooBar] [Foo] [Bar]
  2.  
  3. FooId PK,FK Id PK Id PK
  4. BarId PK,FK BarId FK Name
  5. IsRead Name Description
  6. Description

但是在FooBar中使用PK是必要的,因为EF模型中的每个实体都必须定义一个键属性 – 单个或复合 – 映射到数据库表中的主键.

在这个问题 – Create code first,many to many,with additional fields in association table – 更详细的是如何使用这种类型的关系. (有时人们也称之为“与有效载荷的多对多关系”(IsRead属性是示例模型中的“有效载荷”),但事实上它并不是多对多的.)

猜你在找的C#相关文章