views:

1142

answers:

4

I'm new to Linq to EntityFramework, one question in Linq2EntityFramework I have is when or if to dispose the ObjectContext. The reason I ask this question is that normally in my DAL I have code like

public List<User>  GetUsers()
{
    using (MyEntities db = new MyEntities())   //where MyEntities inherits ObjectContext. 
    {

       // do some linq select operation which returns IQueryable<User>
       // call ToList() on the return IQueryable which is when the DB is really accessed
       // then we return List<User>

    } 
    // after using statement a Dispose method on ObjectContext is called, hence disposed the ObjectContext,  and in turn it closes my DB connection and releases it to the pool
}

Now, I don't want to do this, I want my DAL return IQueryable to my BLL instead of List, so that my BLL can do filtering like Skip() on the returned IQueryable then call ToList() in the BLL. So the code becomes like this,

public IQueryable<User>  GetUsers()
{
   // do some linq select operation which returns IQueryable<User>
   // then just return what we got back
   // Note: no DB access occurred here, this is called deferred execution, because the real DB access happens later in BLL
}

Then in my BLL I have a method like

public List<User>  GetUsers()
{
   // get IQueryable<User> from DAL to a var say users     
    return  users.Skip(10).Take(20).ToList(); // here the DB access really happens.  Note: if we put using in DAL, here will throw exception saying DB is already closed!!
}

My questions are,

  1. If I use the second approach, will Linq2EF know to close my connection after the above method finishes?
  2. With the second approach, ObjectContext is never Disposed, would this be a problem on large sites?
  3. Or how do I get IQuerayable back but still dispose the ObjectContext in DAL?

Thank you so much, Ray.

Edit: One thing I don't understand is that if the connection is smartly managed by the ObjectContext, then is it OK to just not disposing the ObjectContext? What other things beside the ObjectContext manage?

+1  A: 

I tend to think of the EF ObjectContext as the DAL, which gets around this issue. If you want your own DAL to encapsulate the EF stuff (not a horrible idea, IMO), I would suggest making your DAL implement IDisposable.

Daniel Pratt
+1  A: 

If you are in the context of a website, you should seriously consider making it so that your ObjectContext is alive throughout the request.

You need to keep the ObjectContext around for lazy loading, now way around that.

Connections are opened and closed as needed during queries and SaveChanges, so you should not have a "connection leak".

Denis Troller
Thanks a lot for the comment on the connection. By keep ObjectContext alive, do you mean it is okay for me not to dispose it, or in other words, I'm free from surrounding code with using statsment?
ray247
No, it should be instantiated once and disposed at the end of the request cycle.It's pretty easy to do if you are in a webservice, maybe trickier in a WebForms app.You should still dispose the context, but all operations in a request should be carried out on one context.
Denis Troller
A: 

if you want and IQueryable you can do this by querying against the ToList() result and return that

Oscar Cabrero
I think that doing the ToList would cause the IQueryable to enumerate the results and that would cause the read at that point. Ray247 is trying to avoid hitting the database to early hence retuning IQueryable objects rather than List objects.
Pervez Choudhury
Thanks Pervez for the clarification! I think if I don't get definite answer on this one, I'll go with traditional approach where I surround every operation in my DAL with using and return List<> instead of IQueryable<>. Thanks!
ray247
+2  A: 

Regarding your questions:

  1. It will close the open and close the connection with the ToList, since all the enumeration is happening at that place. Only place this can get you with a long opened connection, is if you enumerate over it and run some semi-long processing for each item.
  2. For normal large sites and normal operations, you will be ok with this. The main thing that can get you into trouble is entity tracking, which involves any entity you have loaded. If you are either loading too much information or have a very large site, you can avoid using it (don't sweat it for a normal site).
  3. You can have your data access class implement IDisposable, and dispose the datacontext when it is being disposed. So in your GetUsers you can put an using around your data access class instead.
eglasius
Thank you for the reply and I agree with you! I did more research, there are a couple guys mentioned if they don't dispose the ObjectContext, it caused unwanted locking in DB. I guess if you share context and never dispose it, the entity tracking could be complex to get right.
ray247
To be complete, I read the 2 guys having problem sharing context http://stackoverflow.com/questions/20047/diagnosing-deadlocks-in-sql-server-2005.
ray247
In that post, Jeff said "we are sharing one static datacontext in the base Controller for the most part." Then someone points out Controllers only live for a single request - so at the end of processing a request they are garbage collected. I guess when that happens, the context is disposed.
ray247
@ray247 added a comment to http://stackoverflow.com/questions/20047/diagnosing-deadlocks-in-sql-server-2005/20121#20121 to clear it up, as the property posted isn;t really static, so it lives with the instance of the controller
eglasius
the result of the question/answer was that they changed to use snapshot isolation, no change to the property in the base controller - from that you can tell they are letting it be garbage collected (no dispose).
eglasius
the context isn't meant to be shared across different parallel actions, specially when tracking changes, as you would end up with some weird mixed changes when calling SubmitChanges - this would be the case if sharing the context across different requests
eglasius