Jajan
Jajan

Reputation: 926

Entity Framework core configurations

In EF 6 we could directly pass EntityTypeConfiguration to model builder to build maps and keep our configuration class separate from context without being too verbose in code.

Have they removed those maps in EF core. Is there a way to add configuration without doing it in model builder for every class?

Upvotes: 15

Views: 9761

Answers (3)

user2321864
user2321864

Reputation: 2307

EntityFrameworkCore2.0 has a IEntityTypeConfiguration<TEntity> which can be used as:

class ApplicationUserMap : IEntityTypeConfiguration<ApplicationUser>
{
  public void Configure(EntityTypeBuilder<Customer> builder)
  {
    builder.ToTable("user", "identity");

    builder.Property(p => p.Id)
        .HasColumnName("id");
     ...
   }
}

...
// OnModelCreating
modelBuilder.ApplyConfiguration(new ApplicationUserMap());

Upvotes: 21

Win
Win

Reputation: 62260

Is there a way to add configuration without doing it in model builder for every class?

It definitely is a lot of extra work if you have hundred of tables in database, and you have to configure each and every mapping class manually.

With the help of this extension method, you can achieve the desired result in few line of codes like good old EF 6.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    Type[] types = typeof(EntityTypeConfiguration<>).GetTypeInfo().Assembly.GetTypes();
    IEnumerable<Type> typesToRegister = types
        .Where(type => !string.IsNullOrEmpty(type.Namespace) &&
                        type.GetTypeInfo().BaseType != null &&
                        type.GetTypeInfo().BaseType.GetTypeInfo().IsGenericType &&
                        type.GetTypeInfo().BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));

    foreach (var type in typesToRegister)
    {
        dynamic configurationInstance = Activator.CreateInstance(type);
        ModelBuilderExtensions.AddConfiguration(modelBuilder, configurationInstance);
    }

    base.OnModelCreating(modelBuilder);
}

Extension Method

public abstract class EntityTypeConfiguration<TEntity> where TEntity : class
{
    public abstract void Map(EntityTypeBuilder<TEntity> builder);
}

public static class ModelBuilderExtensions
{
    public static void AddConfiguration<TEntity>(ModelBuilder modelBuilder, EntityTypeConfiguration<TEntity> configuration)
        where TEntity : class
    {
        configuration.Map(modelBuilder.Entity<TEntity>());
    }
}

Mapping Class

public class UserMap : EntityTypeConfiguration<User>
{
    public override void Map(EntityTypeBuilder<User> builder)
    {
        // Primary Key
        builder.HasKey(t => t.Id);
        ...
    } 
}

Upvotes: 10

Cristian Szpisjak
Cristian Szpisjak

Reputation: 2469

The best way is to keep the configuration code away from the OnModelCreating method. So you can do something like:

Create a class where you will store the actual configuration:

public class ApplicationUserConfiguration
{
    public ApplicationUserConfiguration(EntityTypeBuilder<ApplicationUser> entity)
    {
        // Here you have all the good stuff
        entity.ToTable("user", "identity");

        entity.Property(p => p.Id)
            .HasColumnName("id);

        // And so on ....
    }
}

And into your OnModelCreating instantiate the new created class and pass the correct entity:

protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);

    // Your custom configs here
    new ApplicationUserConfiguration(builder.Entity<ApplicationUser>());
}

Is clean and a simple way to achieve the goal.

Upvotes: 15

Related Questions