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 DBContext
s and the pros and cons of each approach?
-
\$\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– acarlon2013年09月06日 06:56:35 +00:00Commented Sep 6, 2013 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– dreza2013年09月06日 08:40:50 +00:00Commented Sep 6, 2013 at 8:40
-
\$\begingroup\$ Thanks, not sure where I picked it up. One DBContext makes sense. \$\endgroup\$acarlon– acarlon2013年09月06日 16:01:07 +00:00Commented Sep 6, 2013 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– Mathieu Guindon2013年09月12日 21:03:31 +00:00Commented Sep 12, 2013 at 21:03
1 Answer 1
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)
-
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– Peter Kiss2013年09月13日 06:06:39 +00:00Commented Sep 13, 2013 at 6:06
-
\$\begingroup\$ Then what, ditch EF and reinvent the wheel? \$\endgroup\$Mathieu Guindon– Mathieu Guindon2013年09月13日 10:52:10 +00:00Commented Sep 13, 2013 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– Peter Kiss2013年10月08日 19:53:56 +00:00Commented Oct 8, 2013 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– AaronLS2014年07月24日 03:56:44 +00:00Commented Jul 24, 2014 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 aCommit
method that callsSaveChanges
- a UoW wraps a transaction, and so does aDbContext
: 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-injectedIUnitOfWork
that exposesIDbSet<T>
for the controller to play with. \$\endgroup\$Mathieu Guindon– Mathieu Guindon2016年08月22日 14:14:49 +00:00Commented Aug 22, 2016 at 14:14
Explore related questions
See similar questions with these tags.