无法将第二个自引用 FK 添加到模型,导致无法确定主体结束错误

Posted

技术标签:

【中文标题】无法将第二个自引用 FK 添加到模型,导致无法确定主体结束错误【英文标题】:Unable to add second self Referencing FK to model, causes Unable to determine the principal end error 【发布时间】:2016-06-09 22:15:43 【问题描述】:

首先,我知道有很多关于 Unable to determine the principal end of an association between the types 错误的帖子,但我看到的任何一个帖子都与我的问题不符,如果我错过了一个很抱歉。

我已经构建了一个实体,它最终会引用它自己两次,当我将代码放入第一次自我引用时,它工作正常,只要添加第二个代码它就会中断。做一些测试,我发现如果我使用他们自己的任何一个自我引用,一切正常,只有当我添加第二个自我引用时它才会中断。我用于自我引用的代码是:

    [ForeignKey("ManagerID")]
    public User Manager  get; set; 

    //Auditing Fields
    public DateTime DateCreated  get; set; 
    public int? UpdatedByUserID  get; set; 
    public DateTime? DateUpdated  get; set; 
    public DateTime LastAutoUpdate  get; set; 

    [ForeignKey("UpdatedByUserID")]
    public User UpdatedByUser  get; set; 

完整的实体代码块是:

public class User

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID  get; set; 

    public int ADPFileNumber  get; set; 

    [Required]
    public string ADUserName  get; set; 

    public int AirCardCheckInLateCount  get; set; 

    [Required]
    public string Email  get; set; 

    public DateTime? EndDate  get; set; 

    [Required]
    public string FirstName  get; set; 

    [Required]
    public string LastName  get; set; 

    public int ManagerID  get; set; 
    public string MobilePhone  get; set; 

    [Required]
    public string Office  get; set; 

    [Required]
    public string Phone  get; set; 

    public decimal PTO  get; set; 
    public DateTime StartDate  get; set; 
    public int VehicleCheckInLateCount  get; set; 
    public int WexCardDriverID  get; set; 

    [ForeignKey("ManagerID")]
    public User Manager  get; set; 

    //Auditing Fields
    public DateTime DateCreated  get; set; 
    public int? UpdatedByUserID  get; set; 
    public DateTime? DateUpdated  get; set; 
    public DateTime LastAutoUpdate  get; set; 

    [ForeignKey("UpdatedByUserID")]
    public User UpdatedByUser  get; set; 

我错过了什么导致第二个自引用中断?

【问题讨论】:

【参考方案1】:

您必须明确指出两个关联的主体端。您可以使用您最初拥有的类来做到这一点,而无需反向集合属性:

modelBuilder.Entity<User>()
            .HasOptional(u => u.Manager)
            .WithMany()
            .HasForeignKey(u => u.ManagerID);
modelBuilder.Entity<User>()
            .HasOptional(u => u.UpdatedByUser)
            .WithMany()
            .HasForeignKey(u => u.UpdatedByUserID);

请注意,ManagerID 也应该是 int?。如果需要另一个用户预先存在,则不能创建任何 User。这是一个先有鸡还是先有蛋的问题。

【讨论】:

这似乎很有效,并且很好地抓住了可空类型,对我来说是一个类型-o。但问题是,这是唯一的方法吗?我宁愿在类中有整个实体定义,而不是拆分出来。 可以使用 Louis 提出的两个逆向集合属性(但也使用 [InverseProperty] 属性)。如果没有这些(您似乎更喜欢),唯一的方法就是使用流畅的映射。【参考方案2】:

正如Multiple self-referencing relationships in Entity Framework 中提到的,您似乎错过了关系的另一部分。

[InverseProperty("Manager")]
public virtual ICollection<User> ManagedUsers get;set;
[InverseProperty("UpdatedByUser")]
public virtual ICollection<User> UpdatedUsers get;set;

编辑:根据@Gert Arnold 的回答,您确实应该添加 [InverseProperty] 属性

【讨论】:

根据您链接的问题和您的答案,我更新了我的代码,虽然现在构建了代码,但它并没有创建第二个密钥。它为 ManagerID 创建 FK,但不为 UpdatedByUserID

以上是关于无法将第二个自引用 FK 添加到模型,导致无法确定主体结束错误的主要内容,如果未能解决你的问题,请参考以下文章

无法将第二个参数传递给带有两个参数的 WCF 服务

如何在不将实例模型添加到数据库的情况下向实体模型添加FK约束?

创建人时,有没有办法在 google people api 中添加第二个自定义字段?

将第二个 UIToolbar 添加到 UITableViewController

将第二个表中的第二个(条件)结果添加到 SQL 查询

第二个查询无法运行