我正在构建一个4层ASP.Net Web应用程序。 这些图层是:
实体层具有我的数据模型类,并使用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?
有没有办法将延迟加载限制为仅发生在数据层中?
答案 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
}