17
\$\begingroup\$

I know that the DBContext represents a session (Unit-Of-Work and Repository) with the database, however I an unsure as to when I should have a different DBContext. Currently, I have a separate DBContext for each table with a single DBSet for each DBContext.

Something like this (Blogs and Posts are in the same database):

public class BlogContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }        
}

public class PostContext : DbContext
{
    public DbSet<Post> Posts { get; set; }
}

I'm not sure why I had a separate DBContext. I think that it is a sample I followed that was like this. However, I recently found that I get an exception when trying to do queries involving both contexts:

The specified LINQ expression contains references to queries that are associated with different contexts.

So, it seems that the obvious solution is for a single DBContext and multiple DBSets:

public class BlogContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }        
    public DbSet<Post> Posts { get; set; }
}

Is there any guideline for when to use different DBContexts and the pros and cons of each approach?

\$\endgroup\$
  • \$\begingroup\$ I suppose one option is to use the Repository and Unit of Work Patterns to manage this across a single repository, but that starts to look like quite a lot of work for a simple site. \$\endgroup\$ – acarlon Sep 6 '13 at 6:56
  • 2
    \$\begingroup\$ Not sure about pros and cons but I have always used one DBContext. I don't think I have ever seen your first example in practice (doesn't mean it's not valid though) \$\endgroup\$ – dreza Sep 6 '13 at 8:40
  • \$\begingroup\$ Thanks, not sure where I picked it up. One DBContext makes sense. \$\endgroup\$ – acarlon Sep 6 '13 at 16:01
  • \$\begingroup\$ My rule of thumb would be to use a single context per app; use multiple contexts when you could be breaking down your app into multiple smaller apps. 99% of the time you would be using a single context. \$\endgroup\$ – Mathieu Guindon Sep 12 '13 at 21:03
15
\$\begingroup\$

As you have already mentioned, DbContext is a UoW, and DbSet is a repository -- there is no need to reimplement those patterns, unless you're into ridiculously useless complexity.

Entity Framework wraps all pending changes in a transaction for you already, so each DbContext in an application contains DbSets that are somehow related. Blogs and Posts are definitely related, so they belong under the same context.

If your app had a blog module and a completely distinct chat module, you could use separate contexts, as your app would never be using both in the same controller.

I have an app with dozens of absolutely unrelated modules; either I defined a single context with 650 entity types (and only used a fraction of it every time), or I broke it down into much smaller and sanely manageable modules... I went for the second option. (the app is an ERP extension)

\$\endgroup\$
  • 1
    \$\begingroup\$ DbSet can not be a repository. A repository should always be an aggragate root and a Blog and Post entity collections belong to one aggreagte root becouse they can not exists without each other. And yes the DbContext is a UoW but this is a wrong implementation and should not rely on it. \$\endgroup\$ – Peter Kiss Sep 13 '13 at 6:06
  • \$\begingroup\$ Then what, ditch EF and reinvent the wheel? \$\endgroup\$ – Mathieu Guindon Sep 13 '13 at 10:52
  • 3
    \$\begingroup\$ @retailcoder: no we don't need to ditch the EF but we have to create another small abstraction layer above it. Image this: we are calling methods which are saving entities to the database, when to call SaveChanges()? Always? Never? If we call it always then we can end up whith a situation when we only saving the half the currently running business transaction. And we havn't talked about that we can have transaction without a database how to handle that? A unit of work belongs to the business logic not (only) to the database abstraction. \$\endgroup\$ – Peter Kiss Oct 8 '13 at 19:53
  • 2
    \$\begingroup\$ @PeterKiss I definitely see the case for a business layer, which is what it sounds like you're describing, which would in turn leverage EF. However, I don't see how repository pattern would be the appropriate pattern for exposing the business layer. A repository pattern represents a set of data. A business layer represents actions that can be performed. \$\endgroup\$ – AaronLS Jul 24 '14 at 3:56
  • 1
    \$\begingroup\$ @RubberDuck you can happily wrap the DbContext with an interface and call it a day. You can even name it IUnitOfWork if you want, and expose a Commit method that calls SaveChanges - a UoW wraps a transaction, and so does a DbContext: they're one and the same. What people want to achieve with the patterns is just a layer between EF and the controller - fine; just saying an interface does exactly that for a fraction of the complexity. I simply cannot see what the problem is with a constructor-injected IUnitOfWork that exposes IDbSet<T> for the controller to play with. \$\endgroup\$ – Mathieu Guindon Aug 22 '16 at 14:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.