Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / EF-Core

EF Core ApplyConfigurations Implementation

4.90/5 (5 votes)
3 Jun 2018CPOL 19.2K  
A quick psedu-code for EF Core that's equivalent to modelBuilder.Configurations.AddFromAssembly in entity framework

Introduction

In entity framework, we've been able to load all "EntityTypeConfiguration" classes using the below method:

C#
modelBuilder.Configurations.AddFromAssembly(assembly)

In EF-Core, this is not available anymore, but we have to add each configuration separately using a generic method that takes the type of the entity as type argument.

C#
modelBuilder.ApplyConfiguration<EntityType>(<code>config</code>)

To add all configurations from specific assembly, we can create an extension method to do the same job as below:

C#
public static void ApplyConfigurationsFromAssembly(this ModelBuilder modelBuilder, Assembly assembly)
{

}

The first thing we'll do is to fetch all configurations that implements the IEntityTypeConfiguration<> interface, knowing that the configuration is a non-abstract non-nested class:

C#
var configurations = assembly.DefinedTypes.Where(t => 
                t.ImplementedInterfaces.Any(i => 
                   i.IsGenericType && 
                   i.Name.Equals(typeof(IEntityTypeConfiguration<>).Name,
                          StringComparison.InvariantCultureIgnoreCase)
                 )&&
                 t.IsClass &&
                 !t.IsAbstract &&
                 !t.IsNested)
                 .ToList();

Then we'll use reflection to invoke the ApplyConfiguration method of the model builder instance for each configuration we have:

C#
foreach (var configuration in configurations) 
{
       var entityType = configuration.BaseType.GenericTypeArguments.SingleOrDefault(t => t.IsClass);

       var applyConfigMethods = typeof(ModelBuilder).GetMethods().Where(m => m.Name.Equals("ApplyConfiguration") && m.IsGenericMethod);
       var applyConfigMethod = applyConfigMethods.Single(m => m.GetParameters().Any(p => p.ParameterType.Name.Equals(typeof(IEntityTypeConfiguration<>).Name)));

       var applyConfigGenericMethod = applyConfigMethod.MakeGenericMethod(entityType); 
       
       applyConfigGenericMethod.Invoke(modelBuilder, 
                    new object[] { Activator.CreateInstance(configuration) }); 
}

The final code will look like below:

C#
public static void ApplyConfigurationsFromAssembly(this ModelBuilder modelBuilder, Assembly assembly)
{
      var configurations = assembly.DefinedTypes.Where(t => 
           t.ImplementedInterfaces.Any(i => 
              i.IsGenericType && 
              i.Name.Equals(typeof(IEntityTypeConfiguration<>).Name,
                     StringComparison.InvariantCultureIgnoreCase)
            )&&
            t.IsClass &&
            !t.IsAbstract &&
            !t.IsNested)
            .ToList();

      foreach (var configuration in configurations)
      {
           var entityType = configuration.BaseType.GenericTypeArguments.SingleOrDefault(t => t.IsClass);

           var applyConfigMethod = typeof(ModelBuilder).GetMethod("ApplyConfiguration");

           var applyConfigGenericMethod = applyConfigMethod.MakeGenericMethod(entityType);

           applyConfigGenericMethod.Invoke(modelBuilder, 
                   new object[] { Activator.CreateInstance(configuration) });
      }
}​​​​​​

Usage

In this example, we'll assume that the configurations exist in the same assembly of the DbContext, so our code will be like:

C#
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
       base.OnModelCreating(modelBuilder);         
       modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)