Entity Framework ‘Code First’ Approach and Domain-Driven Design

By | April 28, 2012

With the Code First approach we can create clean entities without any EF specific code. After the first demo, I saw that you have to deal with the IDbSet interface, which is placed in the Entity Framework library.
When you place the entities in your business dll you have to reference the EF library. This is a bit ugly. After some testing I saw that the IDbSet interface implements the generic IQueryable interface.
So it’s possible to cast the IDbSet to a more common interface.
In this example you will see how to use EF Code First without referencing the EF lib in your business library.

EDIT 15.04.2013:
Based on the user feedback, I decided to extend the VS.NET solution. The first version was focusing on the BL and DAL. The new version contains a possible end-to-end solution. -> ASP.NET MVC – BL – DAL (Entity Framework). What’s new?:

  • Dependency Injection: The CompositionRoot project contains the type mapping definition and is responsible for the type resolution.
  • The UI project references the CompositionRoot (for initializing at startup) and the Business (for accessing the business interfaces.)
  • And again: This blog post still focuses on the technical aspects of EF and persisting domain entities.

Here is a picture of my solution folder. The business dll references only the System lib. This project contains the core logic and the interfaces for the DAL.
The Domain folder contains the entities.

Solution Folder

Solution Folder


The context interface is clean. There are no EF specific types used:

public interface IContext
{
    IQueryable<Person> People { get; set; }
    IQueryable<Address> Addresses { get; set; }
    void Add<T>(T obj) where T : DomainObject;
    void Save();
}

And here are the entities:

public class DomainObject
{
    public Guid MyId { get; set; }
}

public class Person : DomainObject
{
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public ICollection<Address> Addresses { get; set; }
}

public class Address : DomainObject
{
    public string Street { get; set; }
    public string City { get; set; }
    public int Zip { get; set; }
    public virtual Person Person { get; set; }
}

In the infrastructure library I created a context class which implements the IContext interface.

public class Context : DbContext, IContext
{
    public Context()
        : base("MyDb")
    { }

    public IDbSet<Person> PersonSet { get; set; }
    public IDbSet<Address> AddressSet { get; set; }

    public IQueryable<Person> People
    {
        get { return this.PersonSet; }
        set { this.PersonSet = (IDbSet<Person>)value; }
    }

    public IQueryable<Address> Addresses
    {
        get { return this.AddressSet; }
        set { this.AddressSet = (IDbSet<Address>)value; }
    }

    public IQueryable<TEntity> GetSet<TEntity>() where TEntity : class
    {
        return this.Set<TEntity>();
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>()
            .HasKey(x => x.MyId)
            .Property(x => x.MyId)
            .HasColumnName("Id");

        modelBuilder.Entity<Address>().HasKey(x => x.MyId);
            
        base.OnModelCreating(modelBuilder);
    }

    public void Add<T>(T obj) where T : DomainObject
    {
        this.Set<T>().Add(obj);
    }

    public void Save()
    {
        base.SaveChanges();
    }
}

The both public properties PersonSet and AddressSet are used by the EF. But for development, only the properties “People” and “Addresses” are important.
My Entities do not have any entity framework specific Data Annotations like [Key], [ForeignKey] etc.
This definition is made in the OnModelCreating method.
This is it!

Here is the source code.

  • Majid

    Great post.

  • Thiago Cardoso de Castro

    Can you provide this code? I mean: provide the entire project

  • DaMi

    I lost the code, but I created a another solution. Donlwoad: http://blog.micic.ch/wp-content/uploads/2012/04/EfMvc.zip

    The MvcApp project references the Business and Infrastructure (+EF). When you work with Dependency Injection, you just have to reference the business from the UI. (I added the MVC project only for testing purposes.)

  • thedavejau

    This doesnt demonstrate a real world example. It still tightly couples the layers together. Would be nice to see how this would work with a real world application.

  • DaMi

    Hi. It only demonstrates how you can use the EF in DDD. The DAL references the BL an implements the repositories. The UI isn’t well implemented. With DI we could decouple the layers. Right?

    I’ll extend my example so that it makes more sense.

  • Callum Vass

    Hi. First of all this is a great article and the solution you’ve included is easy to follow for a newbie like myself!

    I was just curious why you have the service and call your repositories through that rather then calling your repositories via the Controller?

  • DaMi

    Because I don’t want to implement logic in the Controllers. Controller is in the UI Layer. For example: In a later stage of the project you may have to expose some of the logic via WCF or Web API.. whatever. If you have logic in the Controller you have to duplicate the code. You see what I mean?

  • Callum Vass

    But logic also shouldn’t be in your Repository right? I thought that in DDD, the logic is contained within your model. To me your models defined above are just anaemic models as they just contain properties.

  • DaMi

    Yes. But this tutorial is just an illustration how you can use ADO.NET EF in a DDD architecture. You’re right. The logic has to be in the (domain) model/entities. In my opinion, the repository should contain only query logic.

    Again. This is by far not a complete DDD example.
    Microsoft Spain created an DDD example. I don’t know which persistance technology they have used: http://microsoftnlayerapp.codeplex.com/

  • Guest

    Good article. Can you upload the code again.

  • dmicic

    Hey. Have a look here. I think it’s a better/more extended example:
    http://blog.micic.ch/net/generate-strictly-layered-asp-net-mvc-web-applications

  • Aleksey Filippov

    Can you please explain why do you make a type cast at properties setters:


    set { this.PersonSet = (IDbSet)value; }

  • dmicic

    Hi Aleksey. Good point! Actually, we don’t need a setter. The IQueryable properties are only for the Business layer. The IDbSet properties are initialized by EF and used in the DAL. Therefore, I think we can remove the setter of the IQueryable properties.

  • HichemSeeSharp

    There’s one thing I could’t handle in implementing Bounded context with Entity Framework :
    Having the entities (even their properties) distributed in multiple contexts , I feel the need to centralize the whole model in a specific area, that would be responsible for managing migrations.
    Am I on the right track ? Am I missing an important piece of the implementation puzzle?

  • dmicic

    Having entites in n-contexts is easily possible with EF Model First approach. (You can even “split” the properties in n-entities). But I’ve never done it with Code First.
    Regarding migrations: In one of my projects I don’t use the EF migrations feature. We don’t use any DB initializer and we don’t let EF do any Code-DB model validation. Every DB change is hand written SQL.
    Some people would use Model First in that case. But I still like the puristic approach with Code First.
    (Actually, during development of release 1.0 we used auto migrations to set up the initial DB structure based on our C# code.) But now we don’t have huge DB changes and we can manage the changes easily on our own. (In future we may consider SQL Server Data Tools as an possible way for migrations.)

  • dmicic

    In short: Maybe when you take the responsibility of the DB changes (not EF migrations and disabling the initializer) you “should” be able to have your entity/ies in n-contexts.

  • Chalky

    IQueryable may as well be EF-specific. Ability to substitute one implementation for another is dependent on how it is used elsewhere in your solution. Mark Seeman wrote good article on that.

  • admin

    Thanks Chalky. Fully agree with you. I probably have to update my article and emphasize on the fact that the run-time dependency is still there. If you want to be fully decoupled, the DbContext must not be abstracted through IContext and injected into business.