简体   繁体   中英

Using Entity Framework, how can I add a foreign key on two models to reference each other

I have a ASP.NET MVC 5/C# project. In my project I have two models, Rule and MenuItem . MenuItem has a foreign key that references Rule . And Rule has a foreign key that references MenuItem .

Couple things worth mentioning, my model have a Prefix in the model name. Also, I am using database first approach.

I want to be able to get the MenuItem with the required rule using .Include(...) and also I want to be able to get the Rules with the MenuItem

Here are my models

[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; }
}

However, when I try to pull the menu-items including the required-rule, I get the following error

One or more validation errors were detected during model generation:MenuItem_RequiredRule_Target: : Multiplicity is not valid in Role 'MenuItem_RequiredRule_Target' in relationship 'MenuItem_RequiredRule'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.

I believe this error due to the circular references between my models. However, I need to be able to access both properties either way.

How can I fix this problem?

Entity Framework should be smart enough to figure out that this is 1 to 0/1 relationship. Not tested but this should work?

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; }
}

If you are going this route then you have to make public string Id in the both the Primary and Foreign Key in your Rules table by decorating it with [Key, ForeignKey("PrefixMenuItem")]

See this article for a full example: http://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx

Updated Example:

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; }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM