ASP.Net Entity Framework, objectcontext error
Asked Answered
C

4

11

I'm building a 4 layered ASP.Net web application. The layers are:

  1. Data Layer
  2. Entity Layer
  3. Business Layer
  4. UI Layer

The entity layer has my data model classes and is built from my entity data model (edmx file) in the datalayer using T4 templates (POCO). The entity layer is referenced in all other layers.

My data layer has a class called SourceKeyRepository which has a function like so:

public IEnumerable<SourceKey> Get(SourceKey sk)
{
    using (dmc = new DataModelContainer())
    {
        var query = from SourceKey in dmc.SourceKeys
                    select SourceKey;

        if (sk.sourceKey1 != null)
        {
            query = from SourceKey in query
                    where SourceKey.sourceKey1 == sk.sourceKey1
                    select SourceKey;
        }

        return query;
    }
}

Lazy loading is disabled since I do not want my queries to run in other layers of this application. I'm receiving the following error when attempting to access the information in the UI layer:

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

I'm sure this is because my DataModelContainer "dmc" was disposed. How can I return this IEnumerable object from my data layer so that it does not rely on the ObjectContext, but solely on the DataModel?

Is there a way to limit lazy loading to only occur in the data layer?

Crews answered 21/5, 2010 at 17:49 Comment(0)
L
18

query is lazy evaluated so the data is not retreived from the database until you enumerate it.

If you do:

return query.ToList();

you will force the query to be executed and avoid the problem.

You are receiving the error message because when the caller enumerates the collection, the ObjectContext (dmc) is already disposed thanks to your using clause (which is good - dispose database related resources early!)

Edit

In the original post I used AsEnumerable() which I thought was correct - until I recently tried to use it in this exact situation myself. AsEnumerable() only makes a compile-time type conversion - it doesn't enumerate. To force the query to be enumerated it has to be saved in a List or other collection.

Liesa answered 21/5, 2010 at 17:51 Comment(5)
Just tried it:'System.Linq.IQueryable<Entities.SourceKey>' does not contain a definition for 'ToEnumerable' and no extension method 'ToEnumerable' accepting a first argument of type 'System.Linq.IQueryable<Entities.SourceKey>' could be found (are you missing a using directive or an assembly reference?)Crews
Sorry, I was confusing the names - it should be AsEnumerable just as Tomas suggests. I've updated my answer.Liesa
I adjusted it and now its throwing hte original message that the ObjectContext was disposed.Crews
It didnt like when I had the return within the using... I took it out and now its good to go. THanksCrews
This just doesn't work for me, I still get the errorSniggle
F
5

You could call some method on the query object, for example

return query.AsEnumerable();

That should make sure you execute the query, thus making sure you don't need the object context later.

Fennelly answered 21/5, 2010 at 17:53 Comment(0)
B
5

Don't use

return query.AsEnumerable();

use

return query.ToArray();

before disposing your context.

Returning AsEnumerable won't execute the foreach until the object is referenced. Converting it to an array ensures the foreach executes before your object is disposed. You may put your context in a using block (something you should do) then.

Bronder answered 10/4, 2011 at 6:36 Comment(1)
This may be specific to the new EF 4.1 version. From my experience ToArray worked and AsEnumerable threw the exception. msdn.microsoft.com/en-us/library/gg696167(v=VS.103).aspxKrishna
C
2

In my opinion, this scenario has no relevance with AsEnumerable() or AsQueryable(). Try this;

 public IEnumerable<SourceKey> Get(SourceKey sk, DataModelContainer dmc) {    

    var query = from SourceKey in dmc.SourceKeys
                select SourceKey;

    if (sk.sourceKey1 != null)
    {
        query = from SourceKey in query
                where SourceKey.sourceKey1 == sk.sourceKey1
                select SourceKey;
    }

    return query;

}

And you must get this property with

using (dmc = new DataModelContainer()) {
 // GET
}
Choking answered 26/10, 2010 at 11:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.