GetEntityTypes:使用 .Property<TEntity> 的通用版本配置实体属性.在 EF 核心 [英] GetEntityTypes: configure entity properties using the generic version of .Property&lt;TEntity&gt; in EF Core

查看:16
本文介绍了GetEntityTypes:使用 .Property<TEntity> 的通用版本配置实体属性.在 EF 核心的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 EF 核心项目中,我有一些从基类 DBEntity 继承的实体:

In my EF core project I have a few entities that inherit from a base class DBEntity:

public abstract class DBEntity
{
    public int Id { get; set; }

    public DateTime CreatedOn { get; set; }

    public DateTime UpdatedOn { get; set; }

    public EntityStatus EntityStatus { get; set; }
}

我想为从 DBEntity 继承的每个实体设置一些具有默认值的特定属性.目前我正在使用此代码:

I want to set some specific properties with default value for every entity that inherits from DBEntity. Currently I'm using this code:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {

        var entities = modelBuilder.Model
            .GetEntityTypes()
            .Where(w => w.ClrType.IsSubclassOf(typeof(DBEntity)))
            .Select(p => modelBuilder.Entity(p.ClrType));

        foreach (var entity in entities)
        {

            entity
                .Property("CreatedOn")
                .HasDefaultValueSql("GETDATE()");

            entity
                .Property("UpdatedOn")
                .HasComputedColumnSql("GETDATE()");

            entity
                .Property("EntityStatus")
                .HasDefaultValue(EntityStatus.Created);

        }
    }

这工作正常,但我不想使用字符串常量指定属性名称(不利于重构等).

This works fine but I don't want to specify property names using string constants (bad for refactoring etc.).

有没有办法遍历从 DBEntity 继承的实体并使用属性表达式来配​​置这样的默认值:

Is there a way to loop through entities that inherit from DBEntity and use property expression to configure default values like this:

foreach (var entity in entities)
{
    entity
      .Property(k => k.CreatedOn)
      .HasDefaultValueSql("GETDATE()");

// ....

}

重要约束:我不能直接调用 modelBuilder.Entity().Property(k => k.CreatedOn) 因为它会弄乱所有表.

Important constraint: I cannot directly call modelBuilder.Entity().Property(k => k.CreatedOn) because it will mess up all tables.

推荐答案

正如评论中所指出的,您可以简单地将字符串常量替换为 nameof(DBEntity.CreatedOn) 等.

As pointed out in the comments, you can simply replace the string constants with nameof(DBEntity.CreatedOn) etc.

但如果您想使用类型化访问器,您可以将基本实体配置代码移动到一个泛型方法(泛型参数是实际的实体类型)并通过反射调用它.

But if you want to work with typed accessors, you can move the base entity configuration code to a generic method (with the generic argument being the actual entity type) and call it via reflection.

例如,将以下内容添加到您的 DbContext 派生类:

For instance, add the following to your DbContext derived class:

static void ConfigureDBEntity<TEntity>(ModelBuilder modelBuilder)
    where TEntity : DBEntity
{
    var entity = modelBuilder.Entity<TEntity>();

    entity
        .Property(e => e.CreatedOn)
        .HasDefaultValueSql("GETDATE()");

    entity
        .Property(e => e.UpdatedOn)
        .HasComputedColumnSql("GETDATE()");

    entity
        .Property(e => e.EntityStatus)
        .HasDefaultValue(EntityStatus.Created);

}

然后使用这样的东西:

var entityTypes = modelBuilder.Model
        .GetEntityTypes()
        .Where(t => t.ClrType.IsSubclassOf(typeof(DBEntity)));

var configureMethod = GetType().GetTypeInfo().DeclaredMethods.Single(m => m.Name == nameof(ConfigureDBEntity));
var args = new object[] { modelBuilder };
foreach (var entityType in entityTypes)
    configureMethod.MakeGenericMethod(entityType.ClrType).Invoke(null, args);

这篇关于GetEntityTypes:使用 .Property<TEntity> 的通用版本配置实体属性.在 EF 核心的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆