Click here to Skip to main content
15,867,330 members
Articles / Programming Languages / C#
Tip/Trick

Organizing Fluent Configurations into Separate Classes in EF Core 1.0

Rate me:
Please Sign up or sign in to vote.
5.00/5 (6 votes)
20 Aug 2017CPOL 23.2K   10   6
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)


Written By
Software Developer Afranet
Iran (Islamic Republic of) Iran (Islamic Republic of)
I'm software developer with several years of experience developing software mainly working on web platforms and new technologies.

Comments and Discussions

 
QuestionVery good Idea, but ... Pin
Ahmad Negm24-Oct-17 1:24
Ahmad Negm24-Oct-17 1:24 
QuestionNeat idea, but does it scale? Pin
virusstorm26-Jul-17 7:10
virusstorm26-Jul-17 7:10 
QuestionGood idea, but.. Pin
Chris Voon15-Mar-17 17:47
Chris Voon15-Mar-17 17:47 
Assembly.GetExecutingAssembly()
does not seem to to be available in .NET core.

Given that Reflection is optional in .NET Core, I used static method to have it refactored to separate class files.

Here is how the refactored code looks like:
modelBuilder
   .AddEntity1()
   .AddEntity2()
   ...;

Create extension methods for Entity1 and Entity2. Name them as Entity1Map.cs.

Put the following code for each of the entity map:
using Microsoft.EntityFrameworkCore;
namespace ApplicationName
{
    public static class Entity1Map
    {
        public static ModelBuilder AddSubmissionLog(this ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Entity1>(entity =>
            {
                entity.ToTable(nameof(Entity1));
                entity.HasKey(e => e.Id);
                ...
            });
            return modelBuilder;
        }
    }
}


This way we separate the concerns of registrating the entity with Entity Framework from the details, i.e. the individual columns and their constraints.

In this case we can do away with Reflection, and still achieve separation of concerns.

Hope this is helpful.
AnswerRe: Good idea, but.. Pin
Mohsen Esmailpour23-Jul-17 19:23
professionalMohsen Esmailpour23-Jul-17 19:23 
QuestionColum and table name and relation ship Pin
Kris-I11-Feb-17 21:33
Kris-I11-Feb-17 21:33 
PraiseGreat post Pin
Member 1150234820-Oct-16 16:23
Member 1150234820-Oct-16 16:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.