当前桥接中的添加迁移问题 class(多对多)

Issue on add-migration in this current bridging class (many-to-many)

目前,我们有这个模型 - HostApplicationUser,它是 HostApplicationUser 之间的多对多关系的桥梁(扩展自IdentityUser).

public class HostApplicationUser
{
    public Guid HostID { get; set; }

    public Host Host { get; set; }

    public string Id { get; set; }

    public ApplicationUser ApplicationUser { get; set; }

    public bool IsDeleted { get; set; }

    [Timestamp]
    public byte[] RowVersion { get; set; }

}

在我们的 ApplicationDBContext 中,我们修改了受保护的覆盖 void OnModelCreating(ModelBuilder builder) 以包含如下内容:

// Many to Many relationships

            builder.Entity<HostApplicationUser>()
                .HasKey(bc => new { bc.HostID, bc.Id });


            builder.Entity<HostApplicationUser>()
                .HasOne(bc => bc.Host)
                .WithMany(b => b.HostApplicationUsers)
                .HasForeignKey(bc => bc.HostID);

            builder.Entity<HostApplicationUser>()
                .HasOne(bc => bc.ApplicationUser)
                .WithMany(c => c.HostApplicationUsers)
                .HasForeignKey(bc => bc.Id);

此代码已 运行 正常。但是现在我们有一个新的要求来添加一些 properties/navigation 如下:

public class HostApplicationUser
{
    public Guid HostID { get; set; }

    public Host Host { get; set; }

    public string Id { get; set; }

    public ApplicationUser ApplicationUser { get; set; }

    public DateTime CreatedUTC { get; set; }

    public string CreatedBy { get; set; }

    public DateTime LastModifiedUTC { get; set; }

    public string LastModifiedBy { get; set; }

    public DateTime? DeletedUTC { get; set; }

    public string DeletedBy { get; set; }

    public bool IsDeleted { get; set; }

    [Timestamp]
    public byte[] RowVersion { get; set; }

    [ForeignKey("CreatedBy")]
    public ApplicationUser ApplicationCreatedUser { get; set; }

    [ForeignKey("LastModifiedBy")]
    public ApplicationUser ApplicationLastModifiedUser { get; set; }

}

然后当我们运行添加迁移时出现错误:

Unable to determine the relationship represented by navigation property 'HostApplicationUser.ApplicationCreatedUser' of type 'ApplicationUser'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

关于如何调整解决这个问题的任何想法?我相信这与 OnModelCreating(ModelBuilder builder)有关,以包含其他导航,但不确定如何做到这一点。

谢谢

原因

原因是依赖实体和主体实体对有多个导航属性。考虑 HostApplicationUserApplicationUser 之间的以下关系:

  1. ApplicationUser <-> HostApplicationUser.ApplicationUser
  2. ApplicationUser <-> HostApplicationUser.ApplicationCreatedUser
  3. ApplicationUser <-> HostApplicationUser.ApplicationLastModifiedUser
  4. ...以及 DeletedBy
  5. 的潜在关系

如果您在 ApplicationUser 上有 属性 到 HostApplicationUser 的导航:

public class ApplicationUser{
    public string Id{get;set;}
    public string Name {get;set;}

    public IList<HostApplicationUser> HostApplicationUsers{get;set;} 
}

并且如果没有额外配置,EF Core无法判断Application.HostApplicationUsers属性是否为CreatedUsersLastModifiedUsersDeletedUsers或其他用户,即 EF Core 无法确定 ApplicationUser.HostApplicationUsers 属性 是如何导航到 HostApplicationUser,因此抱怨 :

Unable to determine the relationship represented by navigation property 'HostApplicationUser.ApplicationCreatedUser' of type 'ApplicationUser'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

如何修复

要解决这个问题,只需用 InversePropertyAttribute 装饰 ApplicationUser.HostApplicationUsers :

public class ApplicationUser{
    public string Id{get;set;}
    public string Name {get;set;}

    [InverseProperty("ApplicationUser")]
    public IList<HostApplicationUser> HostApplicationUsers{get;set;} 
}

或者如果想要有多个导航属性,您需要为每个导航添加 [InverseProperty("ApplicationCreatedUser")][InverseProperty("ApplicationLastModifiedUser")][InverseProperty("ApplicationDeletedUser")] 等等 属性 :

public class ApplicationUser{
    public string Id{get;set;}
    public string Name {get;set;}

    [InverseProperty("ApplicationUser")]
    public IList<HostApplicationUser> HostApplicationUsers{get;set;} 

    [InverseProperty("ApplicationCreatedUser")]
    public IList<HostApplicationUser> HostApplicationCreatedUsers{get;set;}

    [InverseProperty("ApplicationLastModifiedUser")]
    public IList<HostApplicationUser> HostApplicationLastModifiedUsers{get;set;}

    // ...
}