【问题标题】: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# 项目。在我的项目中,我有两个模型,RuleMenuItemMenuItem 有一个引用 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/…

标签: c# asp.net-mvc entity-framework asp.net-mvc-5 entity


【解决方案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."} 请记住我使用的是数据库优先方法
  • 对不起,只有一个模型应该是主体。这是经过测试的。我编辑了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-06
  • 1970-01-01
  • 1970-01-01
  • 2020-02-12
  • 2013-11-04
相关资源
最近更新 更多