实体框架Core 2中相同属性的跨域对象的行为不同

时间:2018-07-18 13:43:48

标签: c# .net-core entity-framework-core

我是.NET Core的新手,并且正在使用EF Core 2

我的域对象都是从基类派生的,基类上有一些审核字段,可以根据需要在enumerate上进行设置: (以下简化)

SaveChanges

在添加迁移时,出现错误:

public abstract class AuditableEntity
{
    public DateTime CreatedOn { get; set; }
    [ForeignKey("CreatedBy")]
    public Guid? CreatedByWebUserId { get; set; }
    public WebUser CreatedBy { get; set; }

    public DateTime? UpdatedOn { get; set; }
    [ForeignKey("UpdatedBy")]
    public Guid? UpdatedByWebUserId { get; set; }
    public WebUser UpdatedBy { get; set; }

    public DateTime? DeletedOn { get; set; }
    [ForeignKey("DeletedBy")]
    public Guid? DeletedByWebUserId { get; set; }
    public WebUser DeletedBy { get; set; }
}

Unable to determine the relationship represented by navigation property 'Address.CreatedBy' of type 'WebUser'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'. 是从Address派生的类之一: (以下简化)

AuditableEntity

但是,我有几个对象使用与上面类似的相同“代理程序和时间戳”对模式,并且工作正常,例如:

public class Address : AuditableEntity
{
    public Guid Id { get; set; }
    public string Nickname { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string Address3 { get; set; }
    public string City { get; set; }
    public string StateProvince { get; set; }
    public string PostalCode { get; set; }
    public string CountryCode { get; set; }
    public decimal Latitude { get; set; }
    public decimal Longitude { get; set; }
}

错误总是来自 public DateTime? VerifiedOn { get; set; } [ForeignKey("VerifiedBy")] public Guid? VerifiedByWebUserId { get; set; } public WebUser VerifiedBy { get; set; } ,如果我从“地址”中删除基类,则一切正常(这意味着这些字段已成功应用于我的15个以上其他域对象)。

该问题似乎源于AddressWebUser的引用: (以下简化)

Address

创建这些引用的正确方法是优先保留FK约束(而不是保持导航能力)?

1 个答案:

答案 0 :(得分:2)

该问题与基类的使用无关(如果删除基类,也会发生同样的情况,但是将其属性复制到Address类中),但是多重交叉这两个类之间的引用。

按照惯例,EF Core尝试自动“配对”两个实体的导航属性以形成单个关系,这种关系在大多数情况下都是成功的。但是,在这种情况下,WebUser具有Address类型的导航属性,而Address类具有WebUser类型的导航属性(实际上为3)。

由于它们都通过ForeignKey数据注释具有关联的FK属性,因此EF Core应该能够正确地将它们标识为不同的一对多关系,但事实并非如此。不仅会因所讨论的异常而失败,而且不会为WebUser创建FK关系。

如果基类仅包含1种WebUser类型的导航属性,则一切正常,因此,我很不幸地假设您遇到了一些当前的EF Core错误。

作为一种变通办法,直到他们修复它,我建议通过使用OnModelCreating并添加以下代码来使用流利的API显式配置有问题的关系:

var auditableEntityTypes = modelBuilder.Model.GetEntityTypes().Where(t => t.ClrType.IsSubclassOf(typeof(AuditableEntity)));
var webUserNavigations = new[] { nameof(AuditableEntity.CreatedBy), nameof(AuditableEntity.DeletedBy), nameof(AuditableEntity.UpdatedBy) };
foreach (var entityType in auditableEntityTypes)
{
    modelBuilder.Entity(entityType.ClrType, builder =>
    {
        foreach (var webUserNavigation in webUserNavigations)
            builder.HasOne(typeof(WebUser), webUserNavigation).WithMany();
    });
}

即对于从AuditableEntity派生的每个实体类,我们显式配置3个WebUser参考导航属性以映射到3个独立的一对多关系,而没有逆集合导航属性。完成此操作后,EF Core便不会出现正确映射WebUser.Address FK关联的问题。