简体   繁体   English

实体框架外键引用没有映射

[英]Entity Framework foreign key references not mapping

Using EF6 and .NET 4.6.1. 使用EF6和.NET 4.6.1。 I know this somewhat is a duplicate (I've looked at this stack overflow post ) but hear me out. 我知道这有点重复(我看过这个堆栈溢出帖子 )但是听我说。 My case is different and I have tried to get it to work using their solutions with mine but it didn't work. 我的情况有所不同,我试图让它与我的解决方案一起工作,但它没有用。 So no this isn't actually a duplicate. 所以不,这实际上不是重复。 It's another issue altogether and I haven't found a post that really helps me on this topic. 这是另一个问题,我还没有找到一篇真正帮助我解决这个问题的帖子。

I am trying to map relationships between 3 models; 我试图映射3个模型之间的关系; Employee , Position and Employment . EmployeePositionEmployment I want a one-to-many between Employment and Position (employments map to one position) and a one-to-one between Employment and Employee . 我希望EmploymentPosition之间的一对多(就业映射到一个职位)和EmploymentEmployee之间的一对一。

public class Employment
{
    public int EmploymentID { get; set;}
    ...
    public Position Position { get; set; }
    public Employee Employee { get; set; }
}

public class Position
{
    public int PositionID { get; set;}
    ...
    [InverseProperty("Position")]
    public ICollection<Employment> Employments { get; set; }
}

public class Employee
{
    public int EmployeeID { get; set;}
    ...
    [InverseProperty("Employee")]
    public Employment Employment { get; set; }
}

However, when I try to run this with DbContext automapping, it fails and says it can't find the relationships. 但是,当我尝试使用DbContext运行它时,它会失败并说它无法找到关系。 I've tried multiple combinations of data annotations like setting inverseproperties and foreignkey("____ID") on some of them but haven't been able to get it to work. 我尝试了多种数据注释组合,比如在其中一些设置inverseproperties和foreignkey(“____ ID”),但却无法使其工作。

I did also try adding virtual keywords in for some of the but that didn't do anything either. 我也试过为其中一些添加虚拟关键字,但也没有做任何事情。

I'd rather not use FluentAPI as I want to let the auto mapper do as much as possible with this. 我宁愿不使用FluentAPI,因为我想让自动映射器尽可能地使用它。 It's not complicated a problem enough to warrant manually mapping it with FluentAPI (At least in my opinion it isn't. Maybe I'm wrong). 这不是一个复杂的问题,足以保证用FluentAPI手动映射它(至少在我看来它不是。也许我错了)。

What data annotations do I need? 我需要哪些数据注释? I've looked at this stack overflow post and various articles on entityframeworktutorial.net trying to apply their solutions to my case. 我看过这个堆栈溢出帖子entityframeworktutorial.net上的各种文章试图将他们的解决方案应用到我的案例中。 But haven't gotten anything to work. 但是没有任何工作要做。

The failing line is here: 失败的路线在这里:

using (EmploymentContext ctx = new EmploymentContext())
{
    Position pos = new Position()
    {
        PositionID=1,
        Name="General Manager"
    };
    ctx.Positions.Add(pos); // Failing here
    ctx.SaveChanges();
}

and the error message is: 并且错误消息是:

'Unable to determine the principal end of an association between the types 'Ianmann.Hr.DataAccess.Employment.Employee and Ianmann.Hr.DataAccess.Employment.Employment . '无法确定类型之间关联的主要终点'Ianmann.Hr.DataAccess.Employment.EmployeeIanmann.Hr.DataAccess.Employment.Employment The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.' 必须使用关系流畅API或数据注释显式配置此关联的主要结尾。

I don't know why you insist on using data annotations. 我不知道为什么你坚持使用数据注释。 Everything you can do with data annotation can be done with the Fluent API, but the opposite is not true. 您可以使用Fluent API完成数据注释所能完成的所有工作,但事实恰恰相反。 Also, and especially with relationships, the data annotations are not intuitive and error prone. 此外,特别是对于关系,数据注释不直观且容易出错。

In the concrete case the problem is with the one-to-one relationship (btw, the error message should contain that information). 在具体情况下,问题在于一对一的关系(顺便说一句,错误消息应包含该信息)。 It's because EF cannot determine the principal and the dependent of the relationship when the ends of the relationship are both optional (as in your case) or both required. 这是因为当关系的两端都是可选的(如你的情况)或两者都需要时,EF无法确定关系的主体和依赖关系。 So one way to resolve it is to mark the principal by making the navigation property required: 因此,解决它的一种方法是通过制作所需的导航属性来标记主体:

public class Employment
{
    public int EmploymentID { get; set; }
    ...
    public Position Position { get; set; }

    [Required] // <--
    public Employee Employee { get; set; }
}

The InverseProperty is redundant (not needed) in this case. 在这种情况下, InverseProperty是冗余的(不需要)。

The same can be achieved more intuitively with fluent API: 使用流畅的API可以更直观地实现相同的目标:

modelBuilder.Entity<Employment>()
    .HasRequired(e => e.Employee)
    .WithOptional(e => e.Employment);

But please note that while either way will resolve the issue in question, the resulting design will be the so called Shared Primary Key association , where EmploymentID is both PK and also FK to Employee . 但请注意,虽然任何一种方法都可以解决相关问题,但最终的设计将是所谓的共享主键关联 ,其中EmploymentID既是PK又是Employee FK。 In case you want a separate FK property / column, then fluent API is a must as it cannot be done via data annotations: 如果您需要单独的FK属性/列,则必须使用流畅的API,因为无法通过数据注释完成:

modelBuilder.Entity<Employment>()
    .HasRequired(e => e.Employee)
    .WithOptional(e => e.Employment)
    .Map(m => m.MapKey("EmployeeID"));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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