1

I have an application with 3 layers:

  • UI
  • Domain Services
  • Data

The Data layer uses EF 6 (code first) to connect to the database.

I've create an interface which my DbContext implements:

public interface IMyDbContext
{
    DbSet<TEntity> Set<TEntity>() where TEntity : class;
    int SaveChanges();
    void Dispose();
}

public class MyDbContext : DbContext, IMyDbContext
{
    //...
    public DbSet<Account> Accounts { get; set; }
    public DbSet<Module> Modules { get; set; }
    public DbSet<User> Users { get; set; }
    //...
}

I want to remove the references to EF from the Domain Services layer, that's why I inject this Interface into the Domain Services layer using Dependency Injection.

However the DbSet class is described in the EF binaries, so this is not going to work.

I'd like to use this abstraction in stead of the actual EF implementation, but I'm stuck. I've tried using IQueryable in stead of DbSet, but this didn't work.

I don't want to use (Generic) Repositories, but I want to re-use the DbSet and DbContext functionality of EF in my domain logic.

Rody
  • 2,675
  • 1
  • 22
  • 40
  • possible duplicate of [Remove coupling for EF DBContext and infrastructure layer](http://stackoverflow.com/questions/11059175/remove-coupling-for-ef-dbcontext-and-infrastructure-layer) – jrummell Mar 25 '15 at 19:54

2 Answers2

3

What you are looking for is Unit of Work pattern. It will help you to prevent leaking data logic to the domain layer. Here is a nice tutorial on that.

nikis
  • 11,166
  • 2
  • 35
  • 45
  • 2
    Nikis, in EF6 the DbContext is the Unit of Work and the DbSet's are the repositories. It would be overkill to create an entire seperate Unit of Work. – Rody Mar 25 '15 at 20:12
  • @RodyvanSambeek there is no other way if you want to separate data and domain layers, you need an abstraction in any way. And this is not an overkill, because methods of `UoW` will more or less correspond to EF methods, so it is easy to implement. If you are thinking about performance decrease, take a look on EF overall performance and its stacktrace, you won't feel this decrease. – nikis Mar 25 '15 at 20:16
  • nikis, you are right. But I don't want to lose the flexibility of the DbSet classes of EF6 in my service layer, so I think for simplicity I'm going with referencing the EF6 binaries in my services layer. My Unit Tests can Mock the DbSet to IQueryable for testing, so that's ok. – Rody Mar 25 '15 at 20:18
  • @RodyvanSambeek well, if you don't assume to switch to NHibernate in future or new version of Entity Framework won't break backward compatibilty, this can be done. But it is still not a good design as written in the books. – nikis Mar 25 '15 at 20:22
  • 1
    @RodyvanSambeek _"DbContext is the Unit of Work and the DbSet's are the repositories"_. That's right. I wonder why people can't see that and are constantly making those ridiculous IRepository. And if you are not, then they consider you ignorant and obsolete. – romanoza Mar 25 '15 at 20:22
  • @romanoza because in a such way they are not dependent on a concrete ORM – nikis Mar 25 '15 at 20:24
  • @nikis You are right. But I've never worked on a project when the kind of ORM has been change in the middle of the road. YAGNI. – romanoza Mar 25 '15 at 20:28
  • 1
    @romanoza yes, it depends on the project. The final decision should be made by project lead/architect depending on specification. – nikis Mar 25 '15 at 20:31
  • @romanoza separation of concerns, loose coupling, preventing data logic from leaking into other layers, etc. Simply put, i don't want someone writing what are essentially queries in the business layer anymore than I want someone writing business logic in the presentation layer. Using the DbContext as the UoW and DbSets as repositories is perfectly fine, but so is encapsulating it for a cleaner architecture. – Michael Sep 11 '17 at 21:06
1

A good solution is to use the Repository Pattern (along with Unit of Work) and create one more abstraction of Repository< T >.

http://www.codeproject.com/Articles/526874/Repositorypluspattern-cplusdoneplusright

Silas Reinagel
  • 4,155
  • 1
  • 21
  • 28
  • 1
    Silas, I would like to avoid the Repository pattern to prevent using too much CRUD based approaches. I'd like to use the DbContext inside my services layer which has Command/Query based design. The DbContext (with it's corresponding DbSet's, should be injected into the service layer). – Rody Mar 25 '15 at 20:13