NHibernate什么时候执行我的查询?

时间:2013-03-22 08:44:52

标签: c# linq nhibernate

我正在尝试为我的NHibernate数据访问编写通用存储库。 Get<T>()方法应该能够获取一个可选谓词,该谓词应该包含在查询中 - 也就是说,NHibernate应该在SQL中生成WHERE子句。

    public virtual IList<T> Get(Func<T, bool> predicate = null)
    {
        // Open NHibernate Session
        using (var session = NHibernateHelper.OpenSession())
            return (predicate != null
                       ? session.Query<T>().Where(predicate)
                       : session.Query<T>()).ToList();

    }

当我传入一个谓词,并观察NH生成的SQL语句时,我看不到where子句。

NHibernate何时执行查询?在致电.Query<T>()时才对吗?如果是这样,我怎么能实现这个目标呢?

2 个答案:

答案 0 :(得分:5)

查询应该通过调用ToList()执行。

您的sql语句中未包含WHERE子句的情况是您需要将Expression<Func<T,bool>>传递给您的方法。

public virtual IList<T> Get(Expression<Func<T, bool>> predicate = null)
    {
        // Open NHibernate Session
        using (var session = NHibernateHelper.OpenSession())
            return (predicate != null
                       ? session.Query<T>().Where(predicate)
                       : session.Query<T>()).ToList();

    }

扩展方法Where(Func<T,bool>>)Enumerable上定义,以便查询加载所有数据,然后在内存中应用WHERE过滤器。

扩展方法Where(Expression<Func<T,bool>>)Queryable上定义,以便查询提供程序(NHibernate)可以构建一个sql语句,包括在数据源上执行的WHERE条件。

答案 1 :(得分:1)

由于@Jehof给出了正确的解释,我只想添加单独的注释 - 您不应该从存储库方法返回IList<T>,因为任何其他linq操作将在内存中而不是在数据库中执行。假设以下呼叫

var data = repository.Get<Company>(c=>c.Name.StartsWith("MyCompany"));
... some other operations / method calls etc.
var companySubset = data.Where(...);

所以现在如果你有IList<T> Get<T>()会降低性能,但是使用IQueryable<T> Get<T>,你仍然会在数据库查询中附加第二个Where()。

当然并非IQueryable支持所有linq操作(join,last),这是唯一可以调用ToList()扩展来评估表达式的地方。