65.9K
CodeProject is changing. Read more.
Home

Organizing Fluent Configurations into Separate Classes in EF Core 1.0

starIconstarIconstarIconstarIconstarIcon

5.00/5 (6 votes)

Aug 24, 2016

CPOL
viewsIcon

24315

Organizing Fluent configurations into separate classes in EF Core 1.0

Introduction

As you know, there is no EntityTypeConfiguration class for organizing fluent configuration classes in Entity Framework Core 1.0, but I'm going to show you how to organize fluent configuration in Entity Framework Core 1.0.

Background

Right now, fluent configurating can be done like this:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasMany(b => b.Posts)
        .WithOne();

    modelBuilder.Entity<Post>()
        .HasKey(b => b.Id).
        .Property(b => b.Url).HasMaxLength(500);
    .
    .
    .
}

But when you have many entities, OnModelCreating method will be messy and hard to manage.

Solution

First, create an empty interface.

public interface IEntityMap
{
}

For each entity, create a class for fluent configuration:

public class BlogMap : IEntityMap
{
    public BlogMap(ModelBuilder builder)
    {
        builder.Entity<blog>(b =>
        {
            b.HasKey(e => e.Id);
            b.Property(e => e.Url).HasMaxLength(500).IsRequired();
        });
    }
}

public class PostMap : IEntityMap
{
    public PostMap(ModelBuilder builder)
    {
        builder.Entity<post>(b =>
        {
            b.HasKey(e => e.Id);
            b.Property(e => e.Title).HasMaxLength(128).IsRequired();
            b.Property(e => e.Content).IsRequired();
        });
    }
}

Then, we load mapping classes by reflection:

private void RegisterMaps(ModelBuilder builder)
{
    // Full .NET Framework
    var maps = Assembly.GetExecutingAssembly().GetTypes()
        .Where(type => !string.IsNullOrWhiteSpace(type.Namespace) 
            && typeof(IEntityMap).IsAssignableFrom(type) && type.IsClass).ToList();
            
    // .NET Core
    var maps = typeof(a type in that assembly).GetTypeInfo().Assembly.GetTypes()
        .Where(type => !string.IsNullOrWhiteSpace(type.Namespace) 
            && typeof(IEntityMap).IsAssignableFrom(type) && type.IsClass).ToList();

    foreach (var item in maps)
        Activator.CreateInstance(item, BindingFlags.Public | 
        BindingFlags.Instance, null, new object[] { builder }, null);
}

and inside OnModelCreating method, call RegisterMaps:

protected override void OnModelCreating(ModelBuilder builder)
{
    RegisterMaps(builder);

    base.OnModelCreating(builder);
}