简体   繁体   中英

Is Disposing of Entity Framework context object required

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:

  1. http://blog.jongallant.com/2012/10/do-i-have-to-call-dispose-on-dbcontext.html#.U6WdzrGEeTw
  2. 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 technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM