NHibernate IQueryable似乎没有延迟执行

问题描述 投票:2回答:2

我正在使用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上的广泛扩展方法,改为成为虚拟成员,但是,它们不是)

linq nhibernate linq-to-nhibernate
2个回答
7
投票
您正在从该方法中返回IEnumerable<MyModel>,即使该基础序列为IQueryable<MyModel>,也会从该点开始进行内存中评估。

如果要允许GetActiveMyModel之后的代码添加到SQL查询中,请改为返回IQueryable<MyModel>


1
投票
您正在运行IEnumerable的扩展方法“ Where”,而不是IQueryable的扩展方法。它仍然会懒惰地求值并给出相同的输出,但是它会在入口时求值IQueryable,并且您正在对内存中的集合进行过滤,而不是针对数据库。

[稍后当您在另一个表(计数)上添加额外条件时,它必须从数据库中懒惰地获取每个Item集合,因为它在知道该条件之前已经对IQueryable进行了评估。

© www.soinside.com 2019 - 2024. All rights reserved.