When using ObjectContext in EF 5, should it be a singleton or is it better to create new instance every time like SqlConnection. If so, why?
Create and dispose the context as soon as possible. Quote from the guidelines on MSDN:
Here are some general guidelines when deciding on the lifetime of the
context:
When working with long-running context consider the following:
As you load more objects and their references into memory, the memory
consumption of the context may increase rapidly. This may cause performance issues.
Remember to dispose of the context when it is no
longer required.
If an exception causes the context to be in an
unrecoverable state, the whole application may terminate. The chances
of running into concurrency-related issues increase as the gap between
the time when the data is queried and updated grows.
When working with Web applications, use a context instance per request.
When working with Windows Presentation Foundation (WPF) or Windows Forms, use a
context instance per form. This lets you use change-tracking
functionality that context provides.
Related
Problem:
We have a Blazor server app with a DevExpress grid component, showing data directly from the DB. We want all the operations - filtering, grouping, etc. - to take place on the DB layer, that’s why we don’t use a Service layer to fetch the data, rather we hook directly onto the DB context.
Let’s say we have 2 users, looking at the same grid, each in his own browser (that implicitly means 2 different SignalR connections). User 1 changes the state, but user 2 isn’t aware of that, even if he refreshes the grid. Only when user 2 refreshes the page (F5) are the differences shown.
Explanation:
DB contexts are “scoped DI” by default. In a classic HTTP request-response architecture, that means that for the duration of a request, one and the same instance of the DB context is provided by the DI to all who request it. In the example above, data would be refreshed, because each request will instantiate a new DB context.
In a Blazor app, things are different. DB context in our case is not refreshed with each WEB request. Actually, the term ‘request’ doesn’t even exist in SignalR (WebSocket) and WebAssembly. So, what happens in our example? As long as the SignalR connection is alive, user 2 has the same instance of the DB context. If another user changes state in his own instance of the context, these changes aren’t propagated to other context instances. Roughly, this means that a ‘scoped’ DB context actually becomes a ‘singleton’ (well, almost, singleton in the scope of a user / session / signalR connection).
Links:
https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/dependency-injection
https://learn.microsoft.com/en-us/aspnet/core/blazor/blazor-server-ef-core
https://www.thinktecture.com/blazor/dependency-injection-scopes-in-blazor/
Thoughts:
Our service layer is stateless, so it isn't a problem. DB contexts are problematic
Blazor doesn’t have a concept of a ‘scoped’ service
‘Scoped’ is actually a singleton in the scope of a single connection
‘Singleton’ provides the same service for all the connections
There is an approximation of a scoped service, scoped to the ‘component’ level
Each razor component will use the same instances in its lifetime
But this lifetime can be long lived nonetheless
Another, similar approximation
If truth be told, things are pretty similar to the classic request-response architecture: if 2 requests would happen at exactly the same time, there would be 2 DB context instances with different states. This surely can happen, but the probability of it is low, so it’s not such a problem
Having a ‘transient’ DB context also isn’t OK
we want our API (service layer) methods to be a “unit of work” (1 API - 1 DB transaction)
one API can call multiple BL functions, each in a separate ServiceBL class - those should have the same DB context instances
Solutions:
Scoped is already treated almost the same as a singleton. What if we would register DB contexts as singletons?
Sounds like a bad idea - everybody would use one long-lived instance, it would/could present a bottleneck, what about thread safety?
"EF Core does not support multiple parallel operations being run on the same context instance"
‘Page refresh‘ in the right places can be a substitute for ‘scopes’
await JSRuntime.InvokeVoidAsync("location.reload");
NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true);
When the ‘refresh data grid’ button is clicked, we can create a new instance of the DB context
This is only a solution for this specific case, though. The underlying problem still exists, multiple users have different instances of DB contexts which will sooner or later blow up in our faces
API methods are our unit-of-work. We could manually create a DI scope, use it for the duration of the API and then dispose of it. But that would mean we would have to bubble the services (at least DB context) down to each and every class that would need them :/
Any ideas would be much appreciated
I have a few long running tasks on my server. Basically they are like scheduled tasks - they run from time to time.
They all required access to the DB and I use Entity Framework for that. Each task uses a DbContext for access.
Should the DbContext object be recreated on every run or should I reuse it?
I should say "it depends" as there are probably scenarios where both answers are valid, however the most reasonable answer is "the context should be disposed as soon as it is not needed" which in practice means "dispose rather sooner than later".
The risk that comes from such answer is that newcomers sometimes conclude that the context should be disposed as otfen as possible which sometimes lead to a code I review where there are consecutive "usings" that create a context, use it for one or two operations, dispose and then another context comes up next line. This is of course not recommended also.
In case of web apps, the natural lifecycle is connected with a lifecycle of web requests. In case of system services / other long running applications one of lifecycle strategies is "per business process instance" / "per usecase instance" where business processing / use case implementations define natural borders where separate instances of contexts make sense.
Yes, DbContext should only live for a very short time. It is effectively your unit of work
You should definitely create it each time you're going to use it. (Well, you should inject it but that's another discussion :-))
Update : OK, I accept that 'create it each time you're going to use it' could be misleading. I'm so used to context being an instance on a class that is injected and so lives only for the life of a request that I struggle to think of it any other way... #wiktor's answer is definitely better as it more correctly expresses the idea that you should "dispose sooner rather than later"
I'm struggling with the following problem.
I have a database with a table Jobs, which contains information about Jobs to be done. I followed the Code First approach of EF 6.0 and create a POCO class called Job. I then query the database for the Jobs:
DbSet<Job> receivedJobs;
using (var context = new MyContext())
{
receivedJobs = (from j in context.Jobs
select j);
}
With the received set receivedJobs I will then do a time consuming optimization.
As I understand it, the lifetime of the context as well as the resources the context controls ends with the closing bracket of the using statement. Also a good design should free resources to the database as soon as it is no longer required.
My question is now what should I do in my case? Just keep the database context alive until I finished my time consuming optimisation task. Or close the connection as it is not needed until the optimisation ends. But in the latter case what do I do with the disposed Job objects, because I will then need to access some navigation properties of them which I can't because the context was closed. (And by the way the data in the instances of the Job class will not be changed by the optimization. So it is not required to keep track of changes to these objects, because there will be none)
Hope someone can help me to understand what is the recommended design in this case.
Best regards
You should always hold a context for the least amount of time necessary to do the operations. In your case, it sounds like you will need the context until the optimization is done because you are using some of its methods for navigating the result set. If that is the case, then the context should be held until you don't need it.
The bad habit to avoid is to hold onto a context when you have no immediate need for it. You will see some applications that wrongly create a context on application start and hold it for the life of the application. That is bad and a waste of resources.
In your case, put the optimization code in place, use the context until the code is completed, then release the context. Your using statement will take care of all the messy disposal stuff. Just get your code that needs the context in the {} for the using and you should be good to go.
Altough it will not solve all of your issues, specially the design ones,do you know the "Include" function which preloads the navigation properties of you jobs?
For example if a job points to a list of Tasks thanks to property named "Tasks":
context.Jobs.Include("Tasks") //will preload the Tasks property of
your job.
context.Jobs.Include("Tasks.AllowedUsers") //will preload the Tasks
property of your job, and the AllowedUsers list of each task.
If you want to preload several properties at same level, just use something like:
context.Jobs.Include("Tasks").Include("OtherTasksOnJob")
I was warned not to use more than one DBEntityContext of the Entity Framework in my application. The reason being the risk of deadlock due to concurrent access to the database.
Can anybody confirm this? If this true is it a good idea to implement a Singleton object for the DBContext?
Any Articles on this issue are welcome.
Thank you Advance.
ObjectContext and DbContext are not thread safe. See http://msdn.microsoft.com/library/system.data.objects.objectcontext.aspx. If you use them in a multithreaded environment like ASP.NET, you are running in big trouble when using a single instance. It is recommended to use one ObjectContext per request. The ObjectContext has to be disposed at the end of the request. The Article Managing Entity Framework ObjectContext lifespan and scope in n-layered ASP.NET applications may be helpfull.
Is it possible, that you missunderstood your advisor who told you about deadlocks? May be he wants to warn you about possible deadlocks when using ObjectContext the wrong way.
In web application you have to use a new context instance per each processed web request and dispose the instance after you don't need it any more. Context and anything related to EF is not thread safe. Moreover it implement unit of work and identity map patterns which makes other restrictions on using the context instance.
Dead locks can happen but that is something you must solve by correct transaction design.
I'm using Entity Framework 4.0 behind WCF services. My problem is that the memory used by the programm is growing a lot(start à 200Mo, and I stopped it at ~1.1Go.
How can I manage the cache? I mean, I've two datacontext, one of them is never used to read data, so can I disable the cache?
And for the other, can I specify the amount of space it cans use? Is there a way to monitor these resources? Is there a way to use less resources?
Thank you!
First of all you should not use shared contexts. Create new context for each WCF request and dispose context before you end your operation processing! If you need some data caching do it outside of EF. EF itself is not supposed to be used as cache and there is no control of this behavior.
If you host your service in IIS you can configure AppPool recycling by specifying Private Memory Limit in advanced settings of the AppPool. But it will simply kill everything running in that AppPool.
What may be happening is that each call is creating a new context. Which remains in memory untill the connection timesout and the Garbage collection removes it.
Are you not disposing of the datacontext each time you use it?
Are you closing your connections from the client?
Are you using per call session mode?