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.
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.
I'm implementing a DAL abstraction layer on top of the C# Mongo DB driver using the Repository + Unit of Work pattern.
My current design is that every unit of work instance opens (and closes) a new Mongo DB session.
The problem is that Mongo DB only allows a 1:1 ratio between a session and a transaction, so multiple units of work under the same .NET transaction will not be possible.
The current implementation is:
public class MongoUnitOfWork
{
private IClientSessionHandle _sessionHandle;
public MongoUnitOfWork(MongoClient mongoClient)
{
_sessionHandle = mongoClient.StartSession();
}
public void Dispose()
{
if (_sessionHandle != null)
{
// Must commit transaction, since the session is closing
if (Transaction.Current != null)
_sessionHandle.CommitTransaction();
_sessionHandle.Dispose();
}
}
}
And because of this, the following code won't work. The first batch of data will be committed ahead of time:
using (var transactionScope = new TransactionScope())
{
using (var unitOfWork = CreateUnitOfWork())
{
//... insert items
unitOfWork.SaveChanges();
} // Mongo DB unit of work implementation will commit the changes when disposed
// Do other things
using (var unitOfWork = CreateUnitOfWork())
{
//... insert some more items
unitOfWork.SaveChanges();
}
transactionScope.Complete();
}
Obviously the immediate answer would be to bring all of the changes into one unit of work, but it's not always possible, and also this leaks the Mongo DB limitation.
I thought about session pooling, so that multiple units of work will use the same session, and commit/rollback when the transient transaction completes/aborts.
What other solutions are possible?
Clarification:
The question here is specifically regarding Unit-Of-Work implementation over MongoDB using the MongoDB 4.0 (or later) built-in transaction support.
I never used MongoDB; do not know anything about it. I am only answering in terms of TransactionScope; so not sure if this will help you.
Please refer the Magic Of TransactionScope. IMO, there are three factors you should look for:
Connection to the database should be opened inside the TransactionScope.
So remember, the connection must be opened inside the TransactionScope block for it to enlist in the ambient transaction automatically. If the connection was opened before that, it will not participate in the transaction.
Not sure but it looks that you can manually enlist the connection opened outside the scope using connection.EnlistTransaction(Transaction.Current).
Looking at your comment and the edit, this is not an issue.
All operations should run on same thread.
The ambient transaction provided by the TransactionScope is a thread-static (TLS) variable. It can be accessed with static Transaction.Current property. Here is the TransactionScope code at referencesource.microsoft.com. ThreadStatic ContextData, contains the CurrentTransaction.
and
Remember that Transaction.Current is a thread static variable. If your code is executing in a multi-threaded environments, you may need to take some precautions. The connections that need to participate in ambient transactions must be opened on the same thread that creates the TransactionScope that is managing that ambient transaction.
So, all the operations should run on same thread.
Play with TransactionScopeOption (pass it to constructor of TransactionScope) values as per your need.
Upon instantiating a TransactionScope by the new statement, the transaction manager determines which transaction to participate in. Once determined, the scope always participates in that transaction. The decision is based on two factors: whether an ambient transaction is present and the value of the TransactionScopeOption parameter in the constructor.
I am not sure what your code expected to do. You may play with this enum values.
As you mentioned in the comment, you are using async/await.
Lastly, if you are using async/await inside the TransactionScope block, you should know that it does not work well with TransactionScope and you might want to look into new TransactionScope constructor in .NET Framework 4.5.1 that accepts a TransactionScopeAsyncFlowOption. TransactionScopeAsyncFlowOption.Enabled option, which is not the default, allows TransactionScope to play well with asynchronous continuations.
For MongoDB, see if this helps you.
The MongoDB driver isn't aware of ambient TransactionScopes. You would need to enlist with them manually, or use JohnKnoop.MongoRepository which does this for you: https://github.com/johnknoop/MongoRepository#transactions
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
We are using entity framework for communication with database in our WCF service methods, recently we run the code review tool on our service code. As usual we got many review proposals by tool and many review comments were suggesting to dispose the Entity Framework context object. So, my question is if I use a Entity Framework context object within a method and once I come out of the method, GC doesn't clean up the context object ? do we need to explicitly dispose context object ?
Simply: DbContext implements IDisposable, therefore you should dispose of it, manually, as soon as you're done with it.
You don't need to dispose of it, because the GC will collect it eventually, but the GC isn't deterministic: you never know when "eventually" will be. Until it's disposed, it will be holding resources that aren't in use - for example, it may still have an open database connection. Those resources aren't freed until the GC runs, unless you dispose manually. Depending on specific details you may find that you have unnecessarily blocked network resources, file accesses, and you will certainly be keeping more memory reserved than you need to.
There's a further potential hit, too: when you dispose of an object manually, the GC doesn't typically need to call the Finalizer on that object (if there is one). If you leave the GC to automatically dispose of an object with a Finalizer, it'll place the object in a Finalizer Queue - and will automatically promote the object to the next GC generation. This means that an object with a finalizer will always hang around for orders of magnitude longer than it needs to before being GCed (as successive GC generations are collected less frequently). DBContext would likely fall into this category as the underlying database connection will be unmanaged code.
(Useful reference.)
I think the best approach is coding it within a using statement
using(var cx = new DbContext())
{
//your stuff here
}
so it got automaitaclly disposed
In general if something implements IDisposable it's a Good Idea(TM) to explicitly dispose of it when you're through. This is especially true if you do not own the implementation of said object; you should treat it as a black box in this case. Additionally, even if it were not necessarily "required" to dispose of it now, it may be in the future.
Therefore, IMHO the question of whether you "need to" explicitly dispose of the object is irrelevant. If it is asking to be disposed of - by virtue of implementing IDisposable - it should be disposed of.
The recommended thing to do with a DBContext is to not dispose of it at all (it is the exception to the rule in most cases), even though is a disposable object.
An example of the issue, ths first example is taking a call and evaluation it in the using statement, while the second evaluates it after. (first ons runs, second one throws error The operation cannot be completed because the DbContext has been disposed.)
List<Test> listT;
using (Model1 db = new Model1())
{
listT = db.Tests.ToList(); //ToList Evaluates
}
foreach (var a in listT)
{
Console.WriteLine(a.value);
}
IEnumerable<Test> listT1;
using (Model1 db = new Model1())
{
listT1 = db.Tests;
}
foreach (var a in listT1) //foreach evaluates (but at wrong time)
{
Console.WriteLine(a.value);
}
The same issue happens in
IEnumerable<Test> listT1;
Model1 db = new Model1();
listT1 = db.Tests;
db.Dispose();
foreach (var a in listT1) //foreach evaluates (but at wrong time)
{
Console.WriteLine(a.value);
}
Aslong as you dont open the connection manually you are safe by just using
IEnumerable<Test> listT1;
Model1 db = new Model1();
listT1 = db.Tests;
foreach (var a in listT1) //foreach evaluates (but at wrong time)
{
Console.WriteLine(a.value);
}
and never disposing. as it will take care of itself under most circumstances, as thats what it's designed to do.
Now should you open up a connection by force then the context wont close it automatically when the transfer is done, as it don't know when and then you must/should dispose the object or close the connection and keep the object undisclosed.
Extra midnight reading:
http://blog.jongallant.com/2012/10/do-i-have-to-call-dispose-on-dbcontext.html#.U6WdzrGEeTw
https://msdn.microsoft.com/en-us/data/jj729737.aspx
There is no need to explicitly dispose DbContext.
This is an old hold over from pre-DbContext tools. DbContext is managed code and optimistically maintains database connections on its own. Why sledgehammer it? Whats the hurry? Why not just let the garbage collector decide the best time to clean up when the machine is idle or in need of memory? Also refer to this post: https://blog.jongallant.com/2012/10/do-i-have-to-call-dispose-on-dbcontext/
By not worrying about having to dispose will simplify and optimize your code. Typically I might inherit from a database "helper" class to where I use a getter to either return an already existing DbContext instance, or instantiates a new instance. .
public class DataTools
{
private AppContext _context;
protected AppContext Context => _context ?? (_context = new AppContext());
}
pubic class YourApp : DataTools
{
public void DoLotsOfThings()
{
var = Context.SomeTable.Where(s => s.....);
var stuff = GetSomeThing();
foreach(){}
}
Public string GetSomething()
{
return Context.AnotherTable.First(s => s....).Value;
}
}
The context objects generated by Entity Framework are not thread-safe.
What if I use two separate entity contexts, one for each thread (and call SaveChanges() on each) - will this be thread-safe?
// this method is called from several threads concurrently
public void IncrementProperty()
{
var context = new MyEntities();
context.SomeObject.SomeIntProperty++;
context.SaveChanges();
}
I believe entity framework context implements some sort of 'counter' variable which keeps track of whether the current values in the context are fresh or not.
With the code above - called from separate threads - do I still need to lock around the increment/savechanges?
If so, what is the preferred way to accomplish this in this simple scenario?
More than one thread operating on a single Entity Framework context is not thread safe.
A separate instance of context for each thread is thread-safe. As long as each thread of execution has its own instance of EF context you will be fine.
In your example, you may call that code from any number of threads concurrently and each will be happily working with its own context.
However, I would suggest implementing a 'using' block for this as follows:
// this method is called from several threads concurrently
public void IncrementProperty()
{
using (var context = new MyEntities())
{
context.SomeObject.SomeIntProperty++;
context.SaveChanges();
}
}
You can use the factory approach inject your DbContext as a factory instead of an instance perse, take a look at this: https://github.com/vany0114/EF.DbContextFactory
It's safer and you avoid to hardcode the instance creation into your repositories.
http://elvanydev.com/EF-DbContextFactory/
There is an extension to Ninject to do that in a very easy way, just calling the method kernel.AddDbContextFactory<YourContext>(); also you need to change your repository by receiving a Func<YourContext>
I believe "SomeObject.SomeIntProperty" is static. This has nothing to do with Entity being threadsafe. If you are writing to a Static variables in a multithreaded environment you should always wrap them with a double check lock to ensure thread safety.