Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ApplyConfigurationsFromAssembly With Filter Entityframework Core

I have a requirement to create db context with a specific type of entity since i have multiple Db context on the solution. my problem is OnModelCreating we apply Configuration from the assembly builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()) So i want to apply configuration with only IEntityTypeConfiguration Type with a Entity has base model BaseEntitylike below

public class DaysOfWeekBuilder : IEntityTypeConfiguration<DaysOfWeek>
{
    public void Configure(EntityTypeBuilder<DaysOfWeek> builder)
    {
        builder.ToTable("DaysOfWeek");
        builder.Property(e => e.Name).HasMaxLength(15);
    }
}

So DaysOfWeek Entity has base class BaseEntity

public class DaysOfWeek : BaseEntity
{
    public string Name { get; set; }
}

How can we filter IEntityTypeConfiguration with a Entity has base model BaseEntity ?

Thank you

like image 414
Gayan Avatar asked Jun 06 '26 10:06

Gayan


2 Answers

The documentation says you can add a predicate for filtering as a second argument.

In this case, the predicate will scan the types and for each type, will check if it implements the IEntityTypeConfiguration<T> interface and if T inherits BaseEntity.

builder.ApplyConfigurationsFromAssembly(
    Assembly.GetExecutingAssembly(), 
    t => t.GetInterfaces().Any(i => 
                i.IsGenericType &&
                i.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>) &&
                typeof(BaseEntity).IsAssignableFrom(i.GenericTypeArguments[0]))
);
like image 184
Amir Popovich Avatar answered Jun 08 '26 22:06

Amir Popovich


I had a similar issue where EF Migration would fail because I had the same entity in multiple contexts. And Amir's answer definitely helped me. So based on @Amir's asnwer I made the following.

public static void ApplyConfigurationsForEntitiesInContext(this ModelBuilder modelBuilder)
{
    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]))
        );
}

The point of this is that it looks at all the entities in the current dbcontext and only adds the configurations for the DbSets in the DbContext.

This solved the issue where I had multiple DbContexts in the same assembly and added the configurations by using modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());

using ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()) is especially bad to use if you have multiple contexts in one assembly - it can also make the initial model creation really slow on startup. The reason is that it adds all configurations to a DbContext irregardless of it having a DbSet corresponding to the configuration. As long as it is in the same assembly it is added.

The next step to solving my problem was then to exclude the DbSets from migration that are already being migrated from other DbContexts.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.ApplyConfigurationsForEntitiesInContext();
    modelBuilder.Entity<SomeEntity().Metadata.SetIsTableExcludedFromMigrations(true);
}

I think in the future I will just create separate DbContexts exclusively for migrations and have them in their own assembly. I dislike having code that are not relevant for production in these assemblies.

like image 34
Kent Kostelac Avatar answered Jun 09 '26 00:06

Kent Kostelac



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!