11

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

  1. 数据层
  2. 实体层
  3. 业务层
  4. 界面层

实体层具有我的数据模型类,并且是使用 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

4 回答 4

18

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

如果你这样做:

return query.ToList();

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

您收到错误消息是因为当调用者枚举集合时,dmc由于您的子句,ObjectContext () 已经被释放using(这很好 - 尽早释放与数据库相关的资源!)

编辑

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

于 2010-05-21T17:51:56.300 回答
5

您可以在对象上调用一些方法query,例如

return query.AsEnumerable();

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

于 2010-05-21T17:53:18.633 回答
5

不要使用

return query.AsEnumerable();

采用

return query.ToArray();

在处理您的上下文之前。

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

于 2011-04-10T06:36:04.913 回答
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
}
于 2010-10-26T11:26:25.973 回答