How to filter Bulk register IEntityTypeConfiguration<> by DbContext

Viewed 183

I have multiple DbContext files within the application (multiple databases as well). I would like to filter IEntityTypeConfiguration registration by relevant DbContext.

e.g. I don't want any Account entity references in FirstDbContext or Customer ref. in SecondDbContext.

As per the documentation, I should be able to pass a filter as a second parameter.

How do I go about here?

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());
        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());
        base.OnModelCreating(builder);
    }
}

public class CustomerConfiguration : IEntityTypeConfiguration<Customer>
{
    public void Configure(EntityTypeBuilder<Customer> builder)
    {
        builder.Property(p => p.Id).ValueGeneratedNever();

       // more options here
    }
}

public class AccountConfiguration : IEntityTypeConfiguration<Account>
{
    public void Configure(EntityTypeBuilder<Account> builder)
    {
        builder.Property(p => p.Id).ValueGeneratedNever();

       // more options here
    }
}
1 Answers

The ModelBuilder should have already discovered your DbSet's at the start of OnModelCreating. So you should be able to filter the assembly types by their IEntityTypeConfiguration implementation.

var types = modelBuilder.Model
    .GetEntityTypes()
    .Select(t => t.ClrType)
    .ToHashSet();

modelBuilder.ApplyConfigurationsFromAssembly(
    Assembly.GetExecutingAssembly(), 
    t => t.GetInterfaces()
        .Any(i => i.IsGenericType 
            && i.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>) 
            && types.Contains(i.GenericTypeArguments[0]))
    );

Though you might want a different solution to avoid the performance penalty of scanning the assembly multiple times.

Related