IEnumerable<MyModel>
,即使该基础序列为IQueryable<MyModel>
,也会从该点开始进行内存中评估。如果要允许GetActiveMyModel
之后的代码添加到SQL查询中,请改为返回IQueryable<MyModel>
。
我正在使用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 <100)显然是在.NET中完成的。
此外,如果我将第二个代码块替换为
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
我正在使用NHibernate 3.2,我有一个类似于以下方法的存储库方法:public IEnumerable
GetActiveMyModel(){从Session.Query ([]]]中的m返回] [] 您正在从该方法中返回IEnumerable<MyModel>
,即使该基础序列为IQueryable<MyModel>
,也会从该点开始进行内存中评估。如果要允许
GetActiveMyModel
之后的代码添加到SQL查询中,请改为返回IQueryable<MyModel>
。您正在运行IEnumerable的扩展方法“ Where”,而不是IQueryable的扩展方法。它仍然会懒惰地求值并给出相同的输出,但是它会在入口时求值IQueryable,并且您正在对内存中的集合进行过滤,而不是针对数据库。[稍后当您在另一个表(计数)上添加额外条件时,它必须从数据库中懒惰地获取每个Item集合,因为它在知道该条件之前已经对IQueryable进行了评估。
(是的,我也想成为IEnumerable上的广泛扩展方法,改为成为虚拟成员,但是,它们不是)
IEnumerable<MyModel>
,即使该基础序列为IQueryable<MyModel>
,也会从该点开始进行内存中评估。如果要允许GetActiveMyModel
之后的代码添加到SQL查询中,请改为返回IQueryable<MyModel>
。
[稍后当您在另一个表(计数)上添加额外条件时,它必须从数据库中懒惰地获取每个Item集合,因为它在知道该条件之前已经对IQueryable进行了评估。