使用实体框架,如何在两个模型上添加外键以相互引用
Posted
技术标签:
【中文标题】使用实体框架,如何在两个模型上添加外键以相互引用【英文标题】:Using Entity Framework, how can I add a foreign key on two models to reference each other 【发布时间】:2017-10-16 09:01:33 【问题描述】:我有一个 ASP.NET MVC 5/C# 项目。在我的项目中,我有两个模型,Rule
和 MenuItem
。 MenuItem
有一个引用 Rule
的外键。而Rule
有一个引用MenuItem
的外键。
值得一提的是,我的模型在模型名称中有一个前缀。另外,我使用的是数据库优先方法。
我希望能够使用 .Include(...)
获取具有所需规则的 MenuItem,并且我希望能够使用 MenuItem 获取规则
这是我的模型
[Table("Rules")]
public class PrefixRule
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id get; set;
[ForeignKey("Item")]
public int ModuleId get; set;
public string Name get; set;
public virtual PrefixMenuItem Item get; set;
[Table("MenuItems")]
public class PrefixMenuItem
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id get; set;
[ForeignKey("RequiredRule")]
public int? RequiredRuleId get; set;
public string Name get; set;
public virtual PrefixRule RequiredRule get; set;
但是,当我尝试拉取包含所需规则的菜单项时,出现以下错误
在模型过程中检测到一个或多个验证错误 generation:MenuItem_RequiredRule_Target: : 多重性无效 在关系中的角色“MenuItem_RequiredRule_Target”中 'MenuItem_RequiredRule'。因为从属角色属性不是 关键属性,多重性的上限 从属角色必须是“*”。
我相信这个错误是由于我的模型之间的循环引用。但是,无论哪种方式,我都需要能够访问这两个属性。
我该如何解决这个问题?
【问题讨论】:
实体中的主键在哪里?Because the Dependent Role properties are not the key properties
Ehm 有点跑题了,但我建议您使用 Guids 而不是整数作为 ID。 msdn.microsoft.com/en-us/library/…
【参考方案1】:
如果你要走这条路,那么你必须在规则表的主键和外键中创建公共字符串 ID,方法是用 [Key, ForeignKey("PrefixMenuItem")] 装饰它
完整示例请参阅本文:http://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx
更新示例:
public partial class Rule
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key, ForeignKey("Item")]
public string Id get; set;
[ForeignKey("Module")]
public int ModuleId get; set;
public string Name get; set;
public virtual MenuItem Item get; set;
public virtual Module Module get; set;
public partial class MenuItem
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id get; set;
public string Name get; set;
public virtual Rule RequiredRule get; set;
public partial class Module
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ModuleId get; set;
public string Name get; set;
【讨论】:
我收到此错误"Unable to determine composite primary key ordering for type 'MenuItem'. Use the ColumnAttribute (see http://go.microsoft.com/fwlink/?LinkId=386388) or the HasKey method (see http://go.microsoft.com/fwlink/?LinkId=386387) to specify an order for composite primary keys."
我的两个模型中都已经有一个Key
Id
您是否尝试按照建议进行补救?将列顺序装饰添加到具有您的键的项目? [列(顺序 = 0)]
好吧,等一下,MenuItem 类上的 ModuleId 在哪里。看起来您告诉它导航到那里以通过该外键命名约定找到它。更新我的答案以显示一个希望有所帮助的模拟课程。
您实际上甚至不需要在该事件中进行列排序,因为在这种情况下您需要的唯一原因是如果两个 FK 都指向同一个表【参考方案2】:
实体框架应该足够聪明,能够确定这是 1 对 0/1 的关系。未经测试,但这应该可以吗?
public partial class Rule
[Key, ForeignKey("Item")]
public string ModuleId get; set;
public string Name get; set;
public virtual MenuItem Item get; set;
public partial class MenuItem
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id get; set;
public string Name get; set;
public virtual Rule RequiredRule get; set;
【讨论】:
它并不像你想象的那么聪明。这就是我得到的"Unable to determine the principal end of an association between the types 'Rule' and 'MenuItem'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations."
请记住我使用的是数据库优先方法
对不起,只有一个模型应该是主体。这是经过测试的。我编辑了。以上是关于使用实体框架,如何在两个模型上添加外键以相互引用的主要内容,如果未能解决你的问题,请参考以下文章