ASP.Net Entity Framework,objectcontext错误

时间:2010-05-21 17:49:47

标签: .net lazy-loading objectdisposedexception objectcontext

我正在构建一个4层ASP.Net Web应用程序。 这些图层是:

  1. 数据层
  2. 实体层
  3. 业务层
  4. UI图层
  5. 实体层具有我的数据模型类,并使用T4模板(POCO)从数据层中的实体数据模型(edmx文件)构建。实体层在所有其他层中引用。

    我的数据层有一个名为SourceKeyRepository的类,其函数如下:

    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;
        }
    }
    

    由于我不希望我的查询在此应用程序的其他层中运行,因此禁用了延迟加载。尝试访问UI层中的信息时,我收到以下错误:

      

    ObjectContext实例已经存在   处置,不能再使用了   需要连接的操作。

    我确定这是因为我的DataModelContainer“dmc”被处理掉了。如何从我的数据层返回这个IEnumerable对象,以便它不依赖于ObjectContext,而只依赖于DataModel?

    有没有办法将延迟加载限制为仅发生在数据层中?

4 个答案:

答案 0 :(得分:18)

query是延迟评估的,因此在您枚举数据之前不会从数据库中检索数据。

如果你这样做:

return query.ToList();

您将强制执行查询并避免此问题。

您收到错误消息,因为当调用者枚举集合时,由于您的dmc子句(这很好 - 早期配置数据库相关资源!)已经处理了ObjectContext(using)。

修改

在原帖中,我使用AsEnumerable()我认为是正确的 - 直到我最近尝试在这种情况下自己使用它。 AsEnumerable()仅进行编译时类型转换 - 它不会枚举。要强制查询查询,必须将其保存在List或其他集合中。

答案 1 :(得分:5)

您可以在query对象上调用某个方法,例如

return query.AsEnumerable();

这应确保您执行查询,从而确保您以后不需要对象上下文。

答案 2 :(得分:5)

不要使用

return query.AsEnumerable();

使用

return query.ToArray();

在处理您的上下文之前。

在引用对象之前,返回AsEnumerable将不会执行foreach。将其转换为数组可确保在处理对象之前执行foreach。你可以将你的上下文放在一个使用块(你应该做的事情)中。

答案 3 :(得分:2)

在我看来,这种情况与AsEnumerable()或AsQueryable()无关。试试这个;

 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;

}

你必须用

获得这个属性
using (dmc = new DataModelContainer()) {
 // GET
}