NHibernate IQueryable 似乎不会延迟执行
Posted
技术标签:
【中文标题】NHibernate IQueryable 似乎不会延迟执行【英文标题】:NHibernate IQueryable doesn't seem to delay execution 【发布时间】:2012-01-20 15:43:39 【问题描述】:我正在使用 NHibernate 3.2,并且我有一个如下所示的存储库方法:
public IEnumerable<MyModel> GetActiveMyModel()
return from m in Session.Query<MyModel>()
where m.Active == true
select m;
按预期工作。但是,有时当我使用这种方法时,我想进一步过滤它:
var models = MyRepository.GetActiveMyModel();
var filtered = from m in models
where m.ID < 100
select new m.Name ;
这会产生与第一个相同的 SQL,而第二个过滤器和选择必须在事后完成。我认为 LINQ 的全部意义在于它形成了一个表达式树,在需要时可以解开它,因此可以为该作业创建正确的 SQL,从而保存我的数据库请求。
如果不是,这意味着我的所有存储库方法都必须准确返回所需的内容,并且我不能在不受到惩罚的情况下进一步利用 LINQ。
我是不是搞错了?
更新
针对下面的评论:我省略了迭代结果的行,这导致运行初始 SQL (WHERE Active = 1) 并且第二个过滤器 (ID
另外,如果我将第二段代码替换为
var models = MyRepository.GetActiveMyModel();
var filtered = from m in models
where m.Items.Count > 0
select new m.Name ;
它生成初始 SQL 以检索活动记录,然后为每条记录运行单独的 SQL 语句以找出它有多少项,而不是像我期望的那样编写:
SELECT Name
FROM MyModel m
WHERE Active = 1
AND (SELECT COUNT(*) FROM Items WHERE MyModelID = m.ID) > 0
【问题讨论】:
我不确定你的意思,NHibernates IQueryables 肯定会懒惰地评估。当你得到两个数据库查询并期望一个时,你能举个例子吗?这两个示例都只是创建 Queryable 并且不应该生成任何数据库请求。 【参考方案1】:您正在从该方法返回 IEnumerable<MyModel>
,这将导致从该点开始进行内存评估,即使基础序列是 IQueryable<MyModel>
。
如果您想允许 GetActiveMyModel
之后的代码添加到 SQL 查询中,请改为返回 IQueryable<MyModel>
。
【讨论】:
@littlecharva:有时只需要第二眼。【参考方案2】:您正在运行 IEnumerable 的扩展方法“Where”而不是 IQueryable。它仍然会延迟评估并给出相同的输出,但是它会在输入时评估 IQueryable,并且您正在过滤内存中的集合而不是数据库。
当您稍后在另一个表(计数)上添加额外条件时,它必须从数据库中延迟获取每个 Items 集合,因为它在知道条件之前已经评估了 IQueryable。
(是的,我也想成为 IEnumerable 上的扩展扩展方法,而不是虚拟成员,但是,唉,他们不是)
【讨论】:
以上是关于NHibernate IQueryable 似乎不会延迟执行的主要内容,如果未能解决你的问题,请参考以下文章
NHibernate 3 LINQ:如何过滤 IQueryable 以仅选择 T 类及其子类的对象?
NHibernate 似乎没有批量插入 PostgreSQL