I'm learning ASP.NET MVC and I'm having some questions that the tutorials I've read until now haven't explored in a way that covers me. I've tried searching, but I didn't see any questions asking this. Still, please forgive me if I have missed an existing ones.
If I have a single ASP.NET MVC application that has a number of models (some of which related and some unrelated with each other), how many DbContext
subclasses should I create, if I want to use one connection string and one database globally for my application?
If the answer is one of the first two, then is there anything I should have in mind to make sure that only one database is created for the whole application? I ask because, when debugging locally in Visual Studio, it looks to me like it's creating as many databases as there are contexts. That's why I find myself using the third option, but I'd like to know if it's a correct practice or if I'm making some kind of mistake that will come back and bite me later.
DbContext should not be used as a singleton because it is holding a connection object which cannot be used by multiple threads at the same time. You will run into errors if two requests try to use it at the same time. If your service depends on the context, the service cannot be a singleton.
1 Answer. First, DbContext is a lightweight object; it is designed to be used once per business transaction. Making your DbContext a Singleton and reusing it throughout the application can cause other problems, like concurrency and memory leak issues.
Since DbContext is not thread safe, if your application have async action then it's possible to have multiple thread using your DbContext, which can lead to an exception. On another hand, creating a new DbContext instance doesn't mean open a new connection to DB.
EF and EF Core DbContext types implement IDisposable . As such, best practice programming suggests that you should wrap them in a using() block (or new C# 8 using statement). Unfortunately, doing this, at least in web apps, is generally a bad idea.
@jrummell is only partially correct. Entity Framework will create one database per DbContext type, if you leave it to its own devices. Using the concept of "bounded contexts" that @NeilThompson mentioned from Julie Lerhman, all you're doing is essentially telling each context to actually use the same database. Julie's method uses a generic pattern so that each DbContext that implements it ends up on the same database, but you could do it manually for each one, which would look like:
public class MyContext : DbContext
{
public MyContext()
: base("name=DatabaseConnectionStringNameHere")
{
Database.SetInitializer(null);
}
}
In other words, Julie's method just sets up a base class that each of your contexts can inherit from that handles this piece automatically.
This does two things: 1) it tells your context to use a specific database (i.e., the same as every other context) and 2) it tells your context to disable database initialization. This last part is important because these contexts are now essentially treated as database-first. In other words, you now have no context that can actually cause a database to be created, or to signal that a migration needs to occur. As a result, you actually need another "master" context that will have every single entity in your application in it. You don't have to use this context for anything other than creating migrations and updating your database, though. For your code, you can use your more specialized contexts.
The other thing to keep in mind with specialized contexts is that each instantiation of each context represents a unique state even if they share entities. For example, a Cat
entity from one context is not the same thing as a Cat
entity from a second context, even if they share the same primary key. You will get an error if you retrieved the Cat
from the first context, updated it, and then tried save it via the second context. That example is a bit contrived since you're not likely to have the same entity explicitly in two different contexts, but when you get into foreign key relationships and such it's far more common to run into this problem. Even if you don't explicitly declare a DbSet
for a related entity, it an entity in the context depends on it, EF will implicitly create a DbSet
for it. All this is to say that if you use specialized contexts, you need to ensure that they are truly specialized and that there is zero crossover at any level of related items.
I use what Julie Lerman calls the Bounded Context
The SystemUsers
code might have nothing to do with Products
- so I might have a System DbContext and a Shop DbContext (for example).
Life is easier with a single context in a small app, but for larger application it helps to break the contexts up.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With