在 Entity Framework Code First 中忽略基类型

问题描述 投票:0回答:1

我通常对 EF 实体使用以下接口(.NET 9、EF 9):

public interface IEntity
{
    // Identity column.
    public long Id { get; set; }
    public bool IsAuditable { get; set; }
    public DateTime DateTimeCreated { get; set; }
    public DateTime? DateTimeModified { get; set; }
}

public interface IEntity<TEntity>:
    IEntity
    where TEntity: class, IEntity, IEntity<TEntity>, new()
{ }

我现在正在考虑为所有实体使用具体的基类。考虑以下层次结构:

// Acts as a based class for all entities in the DbContext.
public class EntityBase<TEntity> 
    IEntity<TEntity>
    where TEntity : class, IEntity, IEntity<TEntity>, new()
{
    // Identity column.
    public long Id { get; set; }
    public bool IsAuditable { get; set; }
    public DateTime DateTimeCreated { get; set; }
    public DateTime? DateTimeModified { get; set; }
}

public class DocumentBase:
    EntityBase<DocumentBase>
{
    public string Name { get; set; }
}

public class ElementBase:
    EntityBase<ElementBase>
{
    public string Name { get; set; }
}

// Should represent a database table with all properties
// from the base class but without a discriminator column.
public class Document:
    DocumentBase
{
    public virtual ICollection<Element> Elements { get; set; } = [];
}

// Should represent a database table with all properties
// from the base class but without a discriminator column.
public class Element:
    ElementBase
{
    public long DocumentId { get; set; }
    public virtual Document Document { get; set; }
}

public class ApplicationDbContext:
    DbContext
{
    public DbSet<Document> Documents { get; set; }
    public DbSet<Element> Elements { get; set; }
}

需要注意的几件事:

  • DocumentBase
    ElementBase
    都不需要是抽象的(如果需要,我们应该可以选择将它们标记为抽象)。
  • DbContext
    除了它们的属性之外,应该对这些基类一无所知(就像它们是在具体类中声明的一样)。
  • 各个实体之间唯一的共同点将汇聚于
    ConcreteEntity > ConcreteEntityBase > EntityBase
    。无需考虑其他路径。

生成的表应具有以下声明,没有鉴别器列(无 TPH、TPT):

  • 表:
    Document (Id, IsAuditable, DateTimeCreated, DateTimeModified, Name, Elements)
  • 表:
    Element (COLUMNS: Id, IsAuditable, DateTimeCreated, DateTimeModified, Name, Document, DocumentId)

我发现的最好的资源是这个博客讨论

Table per Concrete Type (TPC)
,但它已经有十多年的历史了,而我正在尝试理解 EF 9。

请注意,这个问题与设计选择或我的方法是否符合最佳实践无关。我只是想知道EF9是否可以实现,如果可以,需要什么配置。

c# .net entity-framework inheritance entity-framework-core
1个回答
0
投票

您不需要为 EF 定义任何继承配置来执行您期望的操作,只要您没有为基类声明任何

DbSet
或实体配置即可。您可能需要的任何显式配置(数据类型、列命名等)只需通过最终子类完成,而不是公共基类。

我的“可编辑”实体项目有类似的基类,它集中了 CreatedByUserId、CreatedDateTime 等公共字段。基本 EnditableEntity 没有表或任何配置,所有配置都基于子类。在我的例子中,EditableEntity 是

abstract
,因为它几乎应该是这样,但我不认为这会直接影响映射。直接引用基类的任何配置或 DbSet 可能会干扰映射并使 EF 期望 TPH/TPT/TPC 配置。

© www.soinside.com 2019 - 2024. All rights reserved.