There is a thing that's been bugging me for a long time about Entity Framework.
Last year I wrote a big application for a client using EF. And during the development everything worked great.
We shipped the system in august. But after some weeks I started to see weird memory leaks on the production-server. My ASP.NET MVC 4 process was taking up all the resources of the machine after a couple of days running (8 GB). This was not good. I search around on the net and saw that you should surround all your EF queries and operations in a using() block so that the context can be disposed.
In a day I refactored all my code to use using() and this solved my problems, since then the process sits on a steady memory usage.
The reason I didn't surround my queries in the first place however is that I started my first controllers and repositories from Microsofts own scaffolds included in Visual Studio, these did not surround it's queries with using, instead it had the DbContext as an instance variable of the controller itself.
First of all: if it's really important to dispose of the context (something that wouldn't be weird, the dbconnection needs to be closed and so on), Microsoft maybe should have this in all their examples!
Now, I have started working on a new big project with all my learnings in the back of my head and I've been trying out the new features of .NET 4.5 and EF 6 async and await. EF 6.0 has all these async methods (e.g SaveChangesAsync, ToListAsync, and so on).
public Task<tblLanguage> Post(tblLanguage language)
{
using (var langRepo = new TblLanguageRepository(new Entities()))
{
return langRepo.Add(RequestOrganizationTypeEnum, language);
}
}
In class TblLanguageRepo:
public async Task<tblLanguage> Add(OrganizationTypeEnum requestOrganizationTypeEnum, tblLanguage language)
{
...
await Context.SaveChangesAsync();
return langaugeDb;
}
However, when I now surround my statements in a using() block I get the exception, DbContext was disposed, before the query has been able to return. This is expected behaviour. The query runs async and the using block is finished ahead of the query. But how should I dispose of my context in a proper way while using the async and await functions of ef 6??
Please point me in the right direction.
Is using() needed in EF 6? Why do Microsoft's own examples never feature that? How do you use async features and dispose of your context properly?
Your code:
public Task<tblLanguage> Post(tblLanguage language)
{
using (var langRepo = new TblLanguageRepository(new Entities()))
{
return langRepo.Add(RequestOrganizationTypeEnum, language);
}
}
is disposing the repository before returning a Task. If you make the code async:
public async Task<tblLanguage> Post(tblLanguage language)
{
using (var langRepo = new TblLanguageRepository(new Entities()))
{
return await langRepo.Add(RequestOrganizationTypeEnum, language);
}
}
then it will dispose the repository just before the Task completes. What actually happens is when you hit the await, the method returns an incomplete Task (note that the using block is still "active" at this point). Then, when the langRepo.Add task completes, the Post method resumes executing and disposes the langRepo. When the Post method completes, the returned Task is completed.
For more information, see my async intro.
I would go for the 'one DbContext per request' way, and reuse the DbContext within the request. As all tasks should be completed at the end of the request anyway, you can safely dispose it again.
See i.e.: One DbContext per request in ASP.NET MVC (without IOC container)
Some other advantages:
some entities might already be materialized in the DbContext from
previous queries, saving some extra queries.
you don't have all those extra using statements cluttering your code.
If you are using proper n-tiered programming patters, your controller should never even know that a database request is being made. That should all happen in your service layer.
There are a couple of ways to do this. One is to create 2 constructors per class, one that creates a context and one that accepts an already existing context. This way, you can pass the context around if you're already in the service layer, or create a new one if it's the controller/model calling the service layer.
The other is to create an internal overload of each method and accept the context there.
But, yes, you should be wrapping these in a using.
In theory, the garbage collection SHOULD clean these up without wrapping them, but I don't entirely trust the GC.
I agree with #Dirk Boer that the best way to manage DbContext lifetime is with an IoC container that disposes of the context when the http request completes. However if that is not an option, you could also do something like this:
var dbContext = new MyDbContext();
var results = await dbContext.Set<MyEntity>.ToArrayAsync();
dbContext.Dispose();
The using statement is just syntactic sugar for disposing of an object at the end of a code block. You can achieve the same effect without a using block by simply calling .Dispose yourself.
Come to think of it, you shouldn't get object disposed exceptions if you use the await keyword within the using block:
public async Task<tblLanguage> Post(tblLanguage language)
{
using (var langRepo = new TblLanguageRepository(new Entities()))
{
var returnValue = langRepo.Add(RequestOrganizationTypeEnum, language);
await langRepo.SaveChangesAsync();
return returnValue;
}
}
If you want to keep your method synchronous but you want to save to DB asynchronously, don't use the using statement. Like #danludwig said, it is just a syntactic sugar. You can call the SaveChangesAsync() method and then dispose the context after the task is completed. One way to do it is this:
//Save asynchronously then dispose the context after
context.SaveChangesAsync().ContinueWith(c => context.Dispose());
Take note that the lambda you pass to ContinueWith() will also be executed asynchronously.
IMHO, it's again an issue caused by usage of lazy-loading. After you disposed your context, you can't lazy-load a property anymore because disposing the context closes the underlying connection to the database server.
If you do have lazy-loading activated and the exception occurs after the using scope, then please see https://stackoverflow.com/a/21406579/870604
Related
I am having an issue where I am encountering the following error: Realms.Exceptions.RealmClosedException
when I try to read my list of realm objects after I retrieved them. The closing of realm is my desired behavior as in my logs I saw ~2K instances of crashes reporting Realm OOM exceptions so I decided to experiment with wrapping my call to realm in a using statement as so:
List<RealmDomain.User> users;
using(var realm = Realm.GetInstance(config))
{
users = realm.All<RealmDomain.User>().ToList();
}
return users;
I then try to work with this data as follows (and that is when the exception is raised)
allUsers.FirstOrDefault(x => x.PortalUserId == id.ToString());. allUsers in this case is the variable holding the data returned by the last block of code. Thus I am wondering what is the correct way to properly handle disposing of realm in order to ensure we don't run into OOM exceptions with it, and how to properly read the data from said source even after it has been closed?
Edit: The block which returns the users is inside of my UserRepository, the application implements the UnitOfWork pattern (to access our realm db) which is then accessed via DI.
Edit2: Another follow up question would be: should I only wrap my calls to realm in a Using statement if it's only a CUD operation (Create, Update, Delete) whilst reads should not be wrapped in that and let the GC handle disposing of the realm instance as needed later?
I think that actually there are multiple points in your question.
Disposing
The way that you dispose your realm really depends on whether you are on the main thread or on a background thread.
If you are on a main thread then you should not dispose your realm, and it would make sense to either call Realm.GetInstance() when you need it, or to initialize the realm as a singleton, like in the following snippet:
public class MyViewModel
{
private readonly Realm realm;
public MyViewModel()
{
this.realm = Realm.GetInstance(); //or this.realm = RealmProvider.Singleton
}
}
If you are on a background thread then you definitely need to dispose of the realm. In this case the using statement is probably the easiest thing to do:
public async Task OnBackgroundThread()
{
using(var realm = Realm.GetInstance()) //From C#8 you don't even need the braces
{
//do work with realm
}
}
You need to dispose of realm on background threads otherwise you will cause the increase of the size of the realm on the disk. You can read more about why in this answer.
ToList()
Using ToList() on realm.All() is probably not a good idea, as you will load all the objects in memory losing the "laziness" of access. If what you need to do is find a certain object you can use a query like:
realm.All<User>().Where(x => x.PortalUserId == id.ToString()).First();
Repository
Realm does not really work well with the repository pattern. If you really want to use the repository pattern, then you will lose some of the advantages of working with realm, like the fact that the objects and collections are live and auto-updating. Besides, this is all made even more complicated by the use of background threads because of what I have said before.
Say I have the following snippet:
using (var db = new dbContext()){
var user = db.Users.Find(3);
user.Name = "newName";
var viewModel = GetViewModelAndDoStuffToUser(user);
db.SaveChanges();
return viewmodel;
}
Now I'm trying to improve the performance of this snippet at scale by leveraging async/await, but I've read that dbContext is not "thread safe". So I'm a bit confused about:
Whether or not I can use async/await with calls relating to dbContext
Whether or not I should use .ConfigureAwait(false) when I do. I've read that this tells us not to re-enter the ".NET Context" which is needed by MVC and WebApi controllers - but this is the service layer of an application serving those controllers. I've also read that using this will prevent deadlocks.
Whether or not - in more complicated scenarios - I can parallelize calls using the same instance of dbContext by using Task.WhenAll()
Would the following snippet be a scalable, thread-safe step in the right direction?
using (var db = new dbContext()){
var user = await db.Users.FindAsync(3).ConfigureAwait(false);
user.Name = "newName";
var viewModel = await GetViewModelAndDoStuffToUserAsync(user).ConfigureAwait(false);
await db.SaveChangesAsync().ConfigureAwait(false);
return viewmodel;
}
Short answer is "Yes", "Yes", and "Yes".
Long answer is that although db context is not thread-safe, async/await constructs are not passing db context to other threads anyway, so you are safe here.
As far as the call to ConfigureAwait(false) goes, you should do it everywhere except UI code. Since database code is rarely placed in UI layer (it is never placed in UI level in high-quality production code) you should use ConfigureAwait(false) in every asynchronous call that you make on backend.
Finally, if you make multiple tasks with calls to async methods of db context, you create co-routines. They parallelize work outside your system (e.g. make concurrent DB calls), but on your end they are not running concurrently. This keeps your db context safe, because any changes to it are applied sequentially.
I am using EF's async methods to fetch data from a database. Most of the time all is well. I have come into a few ObjectContextDisposed exceptions of late, and I am curious as to why my solution works:
Here was my original code that threw ObjectContextDisposed:
public Task<List<string>> GetEventParameterMru(EventParameter parameter, int count = 20)
{
using (var repo = new ConfigurationRepository())
{
return repo.GetEventParameterMRU(_CurrentWorkpack, parameter, count)
}
}
Here is my new code that doesn't throw:
public async Task<List<string>> GetEventParameterMru(EventParameter parameter, int count = 20)
{
using (var repo = new ConfigurationRepository())
{
var result = await repo.GetEventParameterMRU(_CurrentWorkpack, parameter, count);
return result;
}
}
Could someone explain to me what the difference is, and why it works?
Just FYI, in all my usages of this method, I call await GetEventParameterMru()
Thanks
GetEventParameterMRU is apparently a method that starts a Task to retrieve some data. So GetEventParameterMRU returns before all operations on the repo have been completed.
Both version of your code use a using statement, which is translated into a try/finally block. In the finally block, repo will be disposed.
In your first version, you return immediatly after calling GetEventParameterMRU (starting the task). That means that repo is disposed immediatly while the Task using repo is still running. So when this Task accesses repo you receive your
ObjectDisposedException
In the second version you use await. The compiler therefor translates your whole method into a state machine. The method returns control to its caller at the await statement, but without passing the finally block.
When the Task completes, execution of your method is continued after the await statement.
So repo is only disposed when the Task has completed. So you don't get an ObjectDisposedException.
Following is my understanding on initial code review:
In first one, which is not Async implementation but still a Task is returned from the using block, which would call the repo.Dispose() in the end, when finally Task is executed (assuming its done by the caller, but holds true even for the method - GetEventParameterMRU starting it), it's quite feasible that repo is disposed by that time, but still operation is on and thus the exception
In second one, that's not the case, even when it has freed the UI / Calling thread, until and unless following completes:
await repo.GetEventParameterMRU(_CurrentWorkpack, parameter, count)
It will not call repo.Dispose() and thus completely avoid the ObjectContextDisposed issue
Let me translate them for you:
First one:
Create repository
Start GetEventParameterMRU on repository as Task
Dispose repository
return Task, that is still working with repository
Second one:
Create repository
Start GetEventParameterMRU on repository as Task
Wait for Task to finish to get result
Dispose repository
return result
As you can see, the problem is quite clear here.
I believe this has to do with the first code not capturing the current SynchronizationContext explicitly, while await DOES capture this explicitly.
Some further reading:
https://msdn.microsoft.com/en-us/magazine/gg598924.aspx
I have a project on MVC. We chose EF for our DB transactions. We created some managers for the BLL layer. I found a lot of examples, where "using" statement is used, i.e.
public Item GetItem(long itemId)
{
using (var db = new MyEntities())
{
return db.Items.Where(it => it.ItemId == itemId && !it.IsDeleted).FirstOrDefault();
}
}
Here we create a new instance of DBcontext MyEntities().
We using "using" in order to "ensure the correct use of IDisposable objects."
It's only one method in my manager. But I have more than ten of them.
Every time I call any method from the manager I'll be using "using" statement and create another DBcontext in the memory. When will the garbage collector (GC) dispose them? Does anyone know?
But there is alternative usage of the manager methods.
We create a global variable:
private readonly MyEntities db = new MyEntities();
and use DBcontext in every method without "using" statement. And method looks like this:
public Item GetItem(long itemId)
{
return db.Items.Where(it => it.ItemId == itemId && !it.IsDeleted).FirstOrDefault();
}
Questions:
What is the proper way of using DBcontext variable?
What if we wouldn't use "usage" statement (because it affects the performance) - GC will do all for that?
I'm a "rookie" in EF usage and still haven't found the unequivocal answer for this question.
I think you will find many suggesting this style of pattern. Not just me or Henk
DBContext handling
Yes, Ideally Using statements for DBContext subtypes
Even better Unit Of Work patterns that are managed with Using, that have a context and dispose the context Just 1 of many UoW examples, this one from Tom Dykstra
The Unit Of Work Manager should be New each Http request
The context is NOT thread safe so make sure each thread has its own context.
Let EF cache things behind the scenes.
Test Context creation times. after several Http request. Do you still have a concern?
Expect problems if you store the context in static. any sort of concurrent access will hurt and if you are using parallel AJAX calls, assume 90+% chance of problems if using a static single context.
For some performance tips, well worth a read
The proper or best practice way of using DBContext variable is with the Using.
using (var db = new MyEntities())
{
return db.Items.Where(it => it.ItemId == itemId && !it.IsDeleted).FirstOrDefault();
}
The benefit is many things are done automatically for us. For example once the block of code is completed the dispose is called.
Per MSDN EF Working with DbContext
The lifetime of the context begins when the instance is created and
ends when the instance is either disposed or garbage-collected. Use
using if you want all the resources that the context controls to be
disposed at the end of the block. When you use using, the compiler
automatically creates a try/finally block and calls dispose in the
finally block.
The Entity Framework context object implements a Dispose() method which "Releases the resources used by the object context". What does it do really? Could it be a bad thing to always put it into a using {} statement? I've seen it being used both with and without the using statement.
I'm specifically going to use the EF context from within a WCF service method, create the context, do some linq and return the answer.
EDIT: Seems that I'm not the only one wondering about this. Another question is what's really happening inside the Dispose() method. Some say it closes connections, and some articles says not. What's the deal?
If you create a context, you must dispose it later. If you should use the using statement depends on the life time of the context.
If you create the context in a method and use it only within this method, you should really use the using statement because it gives you the exception handling without any additional code.
If you use the context for a longer period - that is the life time is not bound by the execution time of a method - you cannot use the using statement and you have to call Dispose() yourself and take care that you always call it.
What does Dispose()do for an object context?
I did not look at the code, but at least I exspect it to close the database connection with its underlying sockets or whatever resources the transport mechanism used.
Per Progamming Entity Framework: "You can either explicitly dispose the ObjectContext or wait for the garbage collector to do the job."
So in short, while the using statement isn't required, it's best practice if you know you're done using the ObjectContext since the resource is freed up immediately instead of waiting for garbage collection.
Since you don't know when the garbage collector disposes an item, it's always good to wrap up objects that implement IDisposable in a using-block if you know when you're done with it.
EF5 and before version
using { ...
// connecction open here.
...
context.Blogs.Add(blog);
context.SaveChanges(); // query etc now opens and immediately closes
...
context.Blogs.Add(blog);
context.SaveChanges(); // query etc now opens and immediately closes
}
EF6 and after version
using {
// connecction open here.
...
context.Blogs.Add(blog);
context.SaveChanges();
// The underlying store connection remains open for the next operation
...
context.Blogs.Add(blog);
context.SaveChanges();
// The underlying store connection is still open
} // The context is disposed – so now the underlying store connection is closed
Reference: http://msdn.microsoft.com/en-us/data/dn456849#open5
Always, if you instantiate a class that implements IDisposable, then you are responsible for calling Dispose on it. In all but one case, this means a using block.
When you dispose, the ObjectContext disposes other owned objects.
Including things like the EntityConnection which wraps the actual database connection, i.e. generally a SqlConnection.
So 'if' the SqlConnection is open it will be closed when you dispose the ObjectContext.
I realy tested this thing for both ADO.net and EF v.6 and watched connections in SQL table
select * from sys.dm_exec_connections
Methods to be tested looked like this:
1) ADO.net with using
using(var Connection = new SqlConnection(conString))
{
using (var command = new SqlCommand(queryString, Connection))
{
Connection.Open();
command.ExecuteNonQueryReader();
throw new Exception() // Connections were closed after unit-test had been
//finished. Expected behaviour
}
}
2) ADO.net withour using
var Connection = new SqlConnection(conString);
using (var command = new SqlCommand(queryString, Connection))
{
Connection.Open();
command.ExecuteNonQueryReader();
throw new Exception() // Connections were NOT closed after unit-test had been finished
finished. I closed them manually via SQL. Expected behaviour
}
1) EF with using.
using (var ctx = new TestDBContext())
{
ctx.Items.Add(item);
ctx.SaveChanges();
throw new Exception() // Connections were closed, as expected.
}
2) EF without using
var ctx = new TestDBContext();
ctx.Items.Add(item);
ctx.SaveChanges();
throw new Exception() // Connections WERE successfully closed, as NOT expected.
I don't know why is it so, but EF automatically closed connections. Also All the patterns of repository and UnitOfWork which use EF don't use using. It's very strange for me, because DBContext is Disposable type, but it's a fact.
Maybe in Microsoft they did something new for handling?
I have noticed (although in only one application) that the explicit disposal was causing thread abort exceptions in mscorlib which are caught before the application code, but at least in my case resulting in a noticeable performance hit. Haven't done any significant research on the issue, but probably something worth consideration if you are doing this. Just watch your DEBUG output to see if you are getting the same result.
If Dispose closes connection to DB it is a bad idea to call it.
For example in ADO.NET connections are in connection pool and never be closed before timeout or application pool stop.