Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Organizing Fluent Configurations into Separate Classes in EF Core 1.0

5.00/5 (6 votes)
20 Aug 2017CPOL 24.3K  
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:

C#
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.

C#
public interface IEntityMap
{
}

For each entity, create a class for fluent configuration:

C#
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:

C#
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:

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

    base.OnModelCreating(builder);
}

License

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