我使用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; }
}
TenantEntity
和TraceChangesEntity
分别是另一个抽象类和一个空接口。
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
中定义虚拟密钥或将Id
从AfterSalesCoverage
移到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或类似的东西。