使用EF6和.NET 4.6.1。我知道这有点重复(我看过this stack overflow post)但是听我说。我的情况有所不同,我试图让它与我的解决方案一起工作,但它没有用。所以不,这实际上并不重复。这完全是另一个问题,我还没有找到真正帮助我解决这个问题的帖子。
我试图映射3个模型之间的关系; Employee
,Position
和Employment
。我想要Employment
和Position
之间的一对多(就业映射到一个职位)和Employment
和Employee
之间的一对一。
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; }
}
但是,当我尝试使用DbContext
自动执行时运行此功能时,它会失败并说它无法找到关系。我尝试了多种数据注释组合,例如设置inversepperties和foreignkey(&#34; ____ ID&#34;),但是还没有能够让它工作。
我也尝试为某些人添加虚拟关键字,但也没有做任何事情。
我不想使用FluentAPI,因为我想让自动映射器尽可能地使用它。它不是一个复杂的问题,不足以保证用FluentAPI手动映射它(至少在我看来它不是。也许我错了)。
我需要哪些数据注释?我查看了this stack overflow post和entityframeworktutorial.net上的各种文章,试图将他们的解决方案应用到我的案例中。但是没有什么可以发挥作用。
失败的行在这里:
using (EmploymentContext ctx = new EmploymentContext())
{
Position pos = new Position()
{
PositionID=1,
Name="General Manager"
};
ctx.Positions.Add(pos); // Failing here
ctx.SaveChanges();
}
,错误信息为:
&#39;无法确定类型
'Ianmann.Hr.DataAccess.Employment.Employee
和Ianmann.Hr.DataAccess.Employment.Employment
之间关联的主要结尾。必须使用关系流畅API或数据注释显式配置此关联的主要结尾。&#39;
答案 0 :(得分:3)
我不知道为什么你坚持使用数据注释。您可以使用Fluent API完成数据注释所能完成的所有工作,但事实恰恰相反。此外,特别是对于关系,数据注释不直观且容易出错。
在具体情况下,问题在于一对一关系(顺便说一句,错误消息应该包含该信息)。这是因为当关系的两端都是可选的(如你的情况)或两者都需要时,EF无法确定关系的主体和依赖关系。因此,解决它的一种方法是通过制作所需的导航属性来标记主体:
public class Employment
{
public int EmploymentID { get; set; }
...
public Position Position { get; set; }
[Required] // <--
public Employee Employee { get; set; }
}
在这种情况下,InverseProperty
是多余的(不需要)。
使用流畅的API可以更直观地实现同样的目标:
modelBuilder.Entity<Employment>()
.HasRequired(e => e.Employee)
.WithOptional(e => e.Employment);
但请注意,虽然任何一种方法都可以解决相关问题,但最终的设计将是所谓的Shared Primary Key association,其中EmploymentID
既是PK又是FK到Employee
。如果您需要单独的FK属性/列,则必须使用流畅的API,因为无法通过数据注释完成:
modelBuilder.Entity<Employment>()
.HasRequired(e => e.Employee)
.WithOptional(e => e.Employment)
.Map(m => m.MapKey("EmployeeID"));