EF Core:抽象类作为根实体处理

时间:2019-07-09 16:25:27

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

我使用EF核心创建表(首先编写代码),并且某些实体的抽象基类遇到奇怪的行为。我有ConfigurableDiscount类作为抽象基类,并且有多个继承自它的类,例如:AfterSalesCoverage。这些类如下:

public abstract class ConfigurableDiscount : TenantEntity, TraceChangesEntity
{
    public DealType DealType { get; set; }
    [Required]
    [Column(TypeName = "decimal(18,4)")]
    public decimal Discount { get; set; }
}


public class AfterSalesCoverage : ConfigurableDiscount
{
    public Guid Id { get; set; }
    [Required]
    public string Name { get; set; }
}

TenantEntityTraceChangesEntity分别是另一个抽象类和一个空接口。

public abstract class TenantEntity : BaseDeleteEntity
{
    public Guid BusinessUnitId { get; set; }
    public virtual BusinessUnit BusinessUnit { get; set; }
}
public abstract class BaseDeleteEntity : BaseEntity
{
    public DateTime? DeletedOn { get; set; }
}
public abstract class BaseEntity
{
    [Required]
    public DateTime CreatedOn { get; set; }
    public Guid CreatedById { get; set; }
    public virtual User CreatedBy { get; set; }
    public DateTime? ChangedOn { get; set; }
    public Guid? ChangedById { get; set; }
    public virtual User ChangedBy { get; set; }
}

如您所见,所有这些都是抽象的,除了AfterSalesCoverage。 如果我尝试构建或迁移,则会出现以下错误:

  

实体类型'ConfigurableDiscount'需要定义主键。

如果这样做(在ConfigurableDiscount中定义虚拟密钥或将IdAfterSalesCoverage移到ConfigurableDiscount)并尝试迁移,则会收到以下错误消息:

  

不能为实体类型“ AfterSalesCoverage”指定过滤器表达式“ entity =>(entity.DeletedOn == null)”。过滤   er只能应用于层次结构中的根实体类型。

这让我想知道为什么AfterSalesCoverage不是根实体?过滤器表达式是在DBContext中定义/配置的。

编辑: DBContext中的过滤器在OnModelCreating(ModelBuilder builder)内部被调用,如下所示:

private void SetSoftDeleteFilterQuery(ModelBuilder builder)
    {
        System.Collections.Generic.IEnumerable<Type> q = from t in Assembly.GetExecutingAssembly().GetTypes()
                                                         where t.IsClass && t.IsSubclassOf(typeof(BaseDeleteEntity))
                                                         select t;
        foreach (Type type in q)
        {
            MethodInfo method = typeof(CPEDbContext).GetMethod("ApplySoftDeleteFilterQuery", BindingFlags.NonPublic | BindingFlags.Instance);
            MethodInfo generic = method.MakeGenericMethod(type);
            if (type.Name != "RequestWrapper" && type.Name != "TenantEntity" && type.Name != "BaseBenchmarkDiscount")
            {
                {
                    generic.Invoke(this, new[] { builder });
                }
            }
        }
    }

private void ApplySoftDeleteFilterQuery<Tdb>(ModelBuilder builder) where Tdb : BaseDeleteEntity
    {
        builder.Entity<Tdb>().HasQueryFilter(entity => entity.DeletedOn == null);
    }

在这种情况下,似乎此过滤器是关注的中心...

问题: 为什么ConfigurableDiscount需要主键?它不应该是一个实际的实体。如果直接从TenantEntity继承,我在TenantEntity中也不需要ID ... ConfigurableDiscount实体在继承类中没有引用。因此,在我的DBContext中没有DBSet或类似的东西。

0 个答案:

没有答案