首页 > 解决方案 > EF 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或将Idfrom转换AfterSalesCoverageConfigurableDiscount)并尝试迁移,我会收到以下错误:

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

这让我想知道为什么 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 或类似的东西。

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

解决方案


推荐阅读