簡體   English   中英

使用 fluent 在某種類型的實體上配置 EF Core 屬性

[英]Use fluent to configure EF Core properties on entities of a certain type

我有一堆實體,我希望它們具有字段InsertDateUpdateDate ,(SQL)默認值為GETDATE()

為此,我制作了一個簡單的 class AuditableEntity ,我的一堆實體從中派生出來,基本上如下所示:

public class AuditableEntity
{
    InsertDate { get; set; }
    UpdateDate { get; set; }
}

和樣本實體

public class Customer : AuditableEntity
{
    CustomerId int { get; set; }
    // etc..
}

然后,當我使用流利的 API 配置實體時,我可以執行以下操作:

public class CustomerConfiguration : IEntityTypeConfiguration<Customer>
{
    public void Configure(EntityTypeBuilder<Customer> builder)
    {
        builder.Property(e => e.InsertDate)
            .HasDefaultValueSql("getdate()");
        builder.Property(e => e.UpdateDate)
            .HasDefaultValueSql("getdate()");
    }
}

到目前為止,一切都很好。

除了我有一堆這樣的AuditableEntities ,每個 AuditableEntities 都需要設置相同的兩個屬性定義。

是否有一些中心位置可以為所有實體構建屬性,這些實體是AuditableEntity的子類型? 我嘗試了類似下面的方法,但它失敗了,因為它看起來像是在嘗試實例化DbSet<AuditableEntity> ,而我想要做的就是向類型為AuditableEntity的所有實體添加相同的屬性。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<AuditableEntity>(entity =>
        {
            entity.Property(e => e.InsertDate)
                .HasDefaultValueSql("getdate()");
            entity.Property(e => e.UpdateDate)
                .HasDefaultValueSql("getdate()");
        });
    modelBuilder.ApplyConfigurationsFromAssembly(typeof(MyContext).Assembly);
    }
    /* When I try to run add-migration with this in here, it says:
     * system.InvalidOperationException: A key cannot be configured on 'DatasetSource' because it is a derived type. The key must be configured on the root type 'AuditableEntity'. If you did not intend for 'AuditableEntity' to be included in the model, ensure that it is not referenced by a DbSet property on your context, referenced in a configuration call to ModelBuilder, or referenced from a navigation on a type that is included in the model.
     */

選項1;

流利的 API 幫助您配置每個IMutableEntity 但是你可以自己做;

foreach (var table in modelBuilder.Model.GetEntityTypes()){
    if (table.ClrType.IsAssignableTo(typeof(AuditableEntity))){
        foreach(var p in table.GetProperties()
            .Where(p => p.Name == nameof(AuditableEntity.InsertDate) || p.Name == nameof(AuditableEntity.UpdateDate)))
            p.SetDefaultValueSql("getdate()");
    }
}

您可以通過閱讀 github 上的源代碼來了解其他流暢的 api 調用實際上做了什么。

選項 2;

編寫通用方法並從每個IEntityTypeConfiguration實現中手動調用它。

public void ConfigureAuditing<T>(EntityTypeBuilder<T> builder)
    where T:AuditableEntity
{
    builder.Property(e => e.InsertDate)
        .HasDefaultValueSql("getdate()");
    builder.Property(e => e.UpdateDate)
        .HasDefaultValueSql("getdate()");
}

public void Configure(EntityTypeBuilder<Customer> builder){
    ConfigureAuditing(builder);
}

選項 3;

將這兩種方法結合起來。 使用反射和泛型方法調用fluent API;

public void ConfigureAuditing<T>(ModelBuilder modelBuilder)
    where T:AuditableEntity{
    var builder = modelBuilder.Entity<T>();
    // as above
}

var method = new Action<ModelBuilder>(ConfigureAuditing<AuditableEntity>)
    .Method
    .GetGenericMethodDefinition();

foreach (var table in modelBuilder.Model.GetEntityTypes()){
    if (table.ClrType.IsAssignableTo(typeof(AuditableEntity))){
        method.MakeGenericMethod(table.ClrType)
            .Invoke(null, new object[] { modelBuilder });
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM