首页 > 解决方案 > 如何定义一个字段 ONCE,然后在多个实体中使用该定义?

问题描述

我正在使用类继承来添加我的所有实体都必须包含的一组基本字段。当我这样做时,EF Core 会尊重基类中存在的任何数据注释,例如[TimeStamp],在从它继承的类上:

public class SomeClass : BaseEntity
{
    public string SomeEntityField { get; set; }
}

public class BaseEntity
{
    public int Id { get; set; }
    public DateTimeOffset UpdatedDate { get; set; }
    public DateTimeOffset CreatedDate { get; set; }

    [Timestamp]
    public byte[] RowVersion { get; set; }
}

当我想添加所有继承的字段时,上述内容很棒。

但是,如果我希望能够创建一个字段定义 ONCE,然后在其他几个实体中使用该定义,同时还从基类(上面)继承呢?

假设我有这个实体,ItemType

public class ItemType : BaseEntity
{
    [StringLength(28)]
    public string ItemTypeId { get; set; }
    ...

我希望能够ItemTypeId在一个地方定义该字段,然后在包括上表在内的多个实体上使用它,而不必在所有这些实体中手动添加/维护注释。例如,如果我需要使字段更宽[StringLength(50)],我会在一个地方对其进行调整,然后在下一次迁移时更新所有相关字段,因为它们都从相同的定义中“读取”。我试过了

  1. 使用接口,但 EF 不支持接口上的数据注释。
  2. 多重继承,但不能使用,因为我可能需要多个“一次性”字段(并且接口不能按照 #1 工作)

根据CS1721,什么都行不通(好吧,除了单个基类本身)。

我认为理想情况下我希望能够在CommonFieldType下面的代码中定义实体字段,然后让目标实体从它们继承,但不幸的是,由于上述原因,这不起作用。

namespace RDCApp.Shared.CommonFieldType
{   
    public abstract class ItemTypeIdCFT
    {
        [StringLength(28)]
        public string ItemTypeId { get; set; }
    }

    public abstract class AnotherCFT
    {
        [StringLength(100)]
        public string AnotherField { get; set; }
    }

    ...

我不能成为唯一需要/想要这个的人,所以还有其他方法吗?

我知道可以使用 Fluent API,但是我的项目对数据注释的投入如此之大,以至于使用它(以及)感觉不对,这意味着我有 2 个地方可以查看和定义字段属性。直接针对 POCO 进行定义对我来说是正确的!

编辑 为了限定“我觉得正确”的含义:我的 VS 解决方案包括服务器(ASP.NET Core)和客户端(Blazor WASM)项目。两个层都可以“看到”共享项目中的实体/POCO,并且两个层都需要知道注释是什么来执行验证。这意味着我只需要定义一次验证/属性,然后两层都可以看到这一点。

对我来说,Fluent 不是一个合适的选择——尽管如果这是一个典型的服务器端应用程序,我会为 Fluent 拍摄。

标签: c#entity-framework-core

解决方案


您可以定义一个接口和一个通用的 fluent api 帮助器方法来定义字段。

public interface IHasItemType{
    int ItemTypeId { get; set; }
}
public void DefineItemType<T> (EntityTypeBuilder<T> builder) where T:IHasItemType{
    builder.Property(i => i.ItemTypeId) ...
}

或者你可以应用约定OnModelCreating

foreach (var table in modelBuilder.Model.GetEntityTypes())
{
    foreach (var column in table.GetProperties())
    {
        // ...
    }
}

推荐阅读