You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何按对应DbContext过滤批量注册的IEntityTypeConfiguration<>

实现方案

方案1:自定义特性标记(可控性最高,适合复杂场景)

这种方案可以精确控制每个配置类所属的DbContext,支持同一个实体对应不同DbContext使用不同配置的场景。

步骤1:定义关联特性

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class EntityConfigurationForAttribute : Attribute
{
    public Type TargetDbContextType { get; }
    public EntityConfigurationForAttribute(Type targetDbContextType)
    {
        TargetDbContextType = targetDbContextType;
    }
}

步骤2:为配置类添加标记

// 标记该配置仅用于FirstDbContext
[EntityConfigurationFor(typeof(FirstDbContext))]
public class CustomerConfiguration : IEntityTypeConfiguration<Customer>
{
    public void Configure(EntityTypeBuilder<Customer> builder)
    {
        builder.Property(p => p.Id).ValueGeneratedNever();
        // 其余配置逻辑
    }
}

// 标记该配置仅用于SecondDbContext
[EntityConfigurationFor(typeof(SecondDbContext))]
public class AccountConfiguration : IEntityTypeConfiguration<Account>
{
    public void Configure(EntityTypeBuilder<Account> builder)
    {
        builder.Property(p => p.Id).ValueGeneratedNever();
        // 其余配置逻辑
    }
}

步骤3:修改DbContext的配置加载逻辑

在OnModelCreating方法的ApplyConfigurationsFromAssembly中传入过滤规则:

public class FirstDbContext : DbContext
{
    public DbSet<Customer> Customers { get; set; }
    public FirstDbContext (DbContextOptions<FirstDbContext> options) : base(options) { }
    protected override void OnModelCreating(ModelBuilder builder)
    {            
        builder.ApplyConfigurationsFromAssembly(
            Assembly.GetExecutingAssembly(),
            // 仅加载标记为当前DbContext的配置
            type => type.GetCustomAttribute<EntityConfigurationForAttribute>()?.TargetDbContextType == typeof(FirstDbContext)
        );
        base.OnModelCreating(builder);
    }
}

public class SecondDbContext : DbContext
{
    public DbSet<Account> Accounts { get; set; }
    public SecondDbContext (DbContextOptions<SecondDbContext> options) : base(options) { }
    protected override void OnModelCreating(ModelBuilder builder)
    {            
        builder.ApplyConfigurationsFromAssembly(
            Assembly.GetExecutingAssembly(),
            // 仅加载标记为当前DbContext的配置
            type => type.GetCustomAttribute<EntityConfigurationForAttribute>()?.TargetDbContextType == typeof(SecondDbContext)
        );
        base.OnModelCreating(builder);
    }
}

方案2:自动匹配DbSet(无需额外标记,适合常规场景)

如果你的实体仅属于唯一一个DbContext,可以用这个方案,无需添加任何标记,自动根据DbContext中声明的DbSet属性匹配对应的配置。
修改后的DbContext代码如下:

public class FirstDbContext : DbContext
{
    public DbSet<Customer> Customers { get; set; }
    public FirstDbContext (DbContextOptions<FirstDbContext> options) : base(options) { }
    protected override void OnModelCreating(ModelBuilder builder)
    {            
        // 读取当前DbContext所有DbSet对应的实体类型
        var allowedEntityTypes = GetType().GetProperties()
            .Where(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))
            .Select(p => p.PropertyType.GetGenericArguments()[0])
            .ToHashSet();

        builder.ApplyConfigurationsFromAssembly(
            Assembly.GetExecutingAssembly(),
            type => 
            {
                // 校验当前类型是否为实体配置类
                var configInterface = type.GetInterfaces().FirstOrDefault(i => 
                    i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>));
                if (configInterface == null) return false;
                // 读取配置对应的实体类型,判断是否属于当前DbContext
                var entityType = configInterface.GetGenericArguments()[0];
                return allowedEntityTypes.Contains(entityType);
            }
        );
        base.OnModelCreating(builder);
    }
}

public class SecondDbContext : DbContext
{
    public DbSet<Account> Accounts { get; set; }
    public SecondDbContext (DbContextOptions<SecondDbContext> options) : base(options) { }
    protected override void OnModelCreating(ModelBuilder builder)
    {            
        // 读取当前DbContext所有DbSet对应的实体类型
        var allowedEntityTypes = GetType().GetProperties()
            .Where(p => p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))
            .Select(p => p.PropertyType.GetGenericArguments()[0])
            .ToHashSet();

        builder.ApplyConfigurationsFromAssembly(
            Assembly.GetExecutingAssembly(),
            type => 
            {
                // 校验当前类型是否为实体配置类
                var configInterface = type.GetInterfaces().FirstOrDefault(i => 
                    i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>));
                if (configInterface == null) return false;
                // 读取配置对应的实体类型,判断是否属于当前DbContext
                var entityType = configInterface.GetGenericArguments()[0];
                return allowedEntityTypes.Contains(entityType);
            }
        );
        base.OnModelCreating(builder);
    }
}

如果想复用过滤逻辑,也可以把这段逻辑封装为DbContext的扩展方法,减少重复代码。

内容的提问来源于stack exchange,提问作者ecasper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 11:24:03