我有流畅的NHibernate Linq查询,我根据运行时数组检查值。一个基本的例子是:
var array = [1,2,3,4,5,6];
using (var session = SessionProvider.SessionFactory.OpenSession())
{
return session.Query<MyObject>().Where(x => array.Contains(x.CompareVal)).ToList();
}
我希望生成的SQL语句看起来像这样:
SELECT CompareVal, Column1, Column2
FROM MyObject
WHERE CompareVal IN (1,2,3,4,5,6)
但是,我发现的是生成的SQL语句只是发出WHERE子句(通过在Profiler中观察证明)并选择整个表,然后在获取所有数据后似乎在内存中运行过滤器回来。
需要注意的事项 - 我有一个Generic Repository类,所有这些调用都是通过漏洞进行的。 Query方法如下:
public IList<T> Query(Func<T, bool> criteria)
{
using (var session = SessionProvider.SessionFactory.OpenSession())
{
return session.Query<T>().Where(criteria).ToList();
}
}
显然,在具有大量数据的表中,这种情况(缺少where子句)是不可接受的。我该怎么做才能强制NHibernate使用WHERE子句正确生成查询并仍保留存储库的通用模式?
答案 0 :(得分:3)
如果将Query方法更改为以下内容会有所不同吗?
public IList<T> Query(Expression<Func<T, bool>> criteria)
{
using (var session = SessionProvider.SessionFactory.OpenSession())
{
return session.Query<T>().Where(criteria).ToList();
}
}
这就是我通常使用通用查询的方式:
public List<TOut> GetEntitiesLinq<TIn,TOut>(Expression<Func<IQueryable<TIn>,IQueryable<TOut>>> myFunc)
{
var t = (myFunc.Compile())(_session.Query<TIn>()) ;
return t.ToList();
}
然后我会如何在你的情况下使用它:
var myObjList = myQueryManager.GetEntitiesLinq<MyObject,MyObject>(x=>x.Where(myObj => array.Contains(myObj.CompareVal)));
希望这会有所帮助
答案 1 :(得分:2)
使用任何:
return session.Query<MyObject>().Where(x => array.Any(y => y == x.CompareVal)).ToList();
您的存储库模式(使用普通Func)会自动将您的查询实现为列表,如果您想要延迟执行某些内容,请使用IQueryable,不要仅使用Func
需要注意的事项 - 我有一个Generic Repository类 这些电话都是通过电话进行的。 Query方法如下:
public IList<T> Query(Func<T, bool> criteria)
{
using (var session = SessionProvider.SessionFactory.OpenSession())
{
return session.Query<T>().Where(criteria).ToList();
}
}
您的存储库只是模仿NHibernate已经开箱即用的内容
答案 2 :(得分:0)
您可以使用QueryOver和WhereRestrictionOn吗?
session.QueryOver<MyObject>().WhereRestrictionOn(o => o.CompareVal).IsIn(array).List();