C# 使用Linq查询计数的NHibernate期货

C# 使用Linq查询计数的NHibernate期货,c#,sql,linq,nhibernate,C#,Sql,Linq,Nhibernate,我在下面有一个方法,通过数据库查询以获取例如用户、订单或任何实体。我想知道下面的查询是否是最优的,或者我是否需要调整它 只有在将所有记录存储在内存中之后,查询才会在何处执行 是否有一种方法可以为筛选指定表达式,而不是Func 获取计数的最佳方法是什么,指定一个条件/位置而不消耗太多内存 C#示例代码 public IList<TEntity> Find(Func<TEntity, bool> predicate) { //Criteria for creating

我在下面有一个方法,通过数据库查询以获取例如用户、订单或任何实体。我想知道下面的查询是否是最优的,或者我是否需要调整它


只有在将所有记录存储在内存中之后,查询才会在何处执行

是否有一种方法可以为筛选指定
表达式
,而不是
Func

获取计数的最佳方法是什么,指定一个条件/位置而不消耗太多内存

C#示例代码

public IList<TEntity> Find(Func<TEntity, bool> predicate)
{
    //Criteria for creating
    ICriteria filterCriterea = _unitOfWork.CurrentSession.CreateCriteria(typeof(TEntity));

    //filtered result
    return filterCriterea.Future<TEntity>().Where(predicate).ToList();
}
公共IList查找(Func谓词)
{
//创建的标准
icriteriafiltercriterea=_unitOfWork.CurrentSession.CreateCriteria(typeof(tenty));
//过滤结果
返回filterCriterea.Future().Where(谓词).ToList();
}

以下是您需要解决的几个问题:

1.询问一个
表达式,而不是
Func
您的
Find
方法指定它需要一个
Func
。如果您想要一个
表达式
,您必须这样说:

public IList<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
如果要在其中包含where子句,则必须切换这些方法调用:

filterCriterea.Where(predicate).Future<TEntity>()
了解
IQueryable
IEnumerable
之间的区别非常重要。您应该注意,
Query
返回一个
IQueryable
,而
Future
返回一个
IEnumerable
。使用
表达式操作
IQueryable
将导致执行的SQL发生更改。使用
Func
操作
IEnumerable
只会改变查看内存中数据的方式

4.
ToList
紧接着
Future
否定了
Future
ToList
迭代传递给它的集合,并将每个元素放入列表中。迭代集合的行为将导致立即执行未来的查询,而不会给您任何机会将其与其他查询一起批处理。如果您必须有一个列表,您只需省略
将来的内容
。但是,我认为最好更改方法以返回一个
IEnumerable
,这将使您能够将此查询与其他查询一起批处理。就像这样

public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
{
    var query = _unitOfWork.CurrentSession.Query<TEntity>();
    return query.Where(predicate).Future<TEntity>();
}
。。。您应该这样做:

var openThings = thingRepository.Find(x => x.Status == Status.Open);
var negativeWhatsits = whatsitRepository.Find(x => x.Amount < 0);

// both queries will be executed here in one round-trip to database
foreach (var openThing in openThings)
    CloseIt(openThing);

foreach (var negativeWhatsit in negativeWhatsits)
    BePositive(negativeWhatsit);
var openThings=thingRepository.Find(x=>x.Status==Status.Open);
var negativeWhatsits=whatsitRepository.Find(x=>x.Amount<0);
//这两个查询将在数据库的一次往返中执行
foreach(openThings中的var openThing)
关闭它(打开东西);
foreach(var negativeWhatsit in negativeWhatsits)
阳性(阴性)whatsit;

“只有在将所有记录存储在内存中后,查询才会在何处执行?”:是。可能会有所帮助。您使用的是什么版本的NHibernate?@DanielSchilling V2.1.2严格要求不要更改版本aahh!!!我完全忽略了这样一个事实,即您试图在ICriteria中使用表达式和LINQ风格的过滤。那是不可能的。如果要使用表达式,则需要使用LINQ或QueryOver。编辑…
\u unitOfWork.CurrentSession.Query()为什么Visual Studio抱怨我方法查询不存在,是因为NHibernate 2.1吗?是的。LINQ支持已正式添加到NHibernate 3.0版,但您可以使用nhcontrib中的LINQ提供程序将LINQ支持添加到NHibernate 2.1:。在引用NHibernate.Linq.dll之后,使用NHibernate.Linq添加
到文件的顶部。这将为您提供一个
session.Linq()
扩展方法(而不是
session.Query()
)。
public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
{
    var query = _unitOfWork.CurrentSession.Query<TEntity>();
    return query.Where(predicate).Future<TEntity>();
}
foreach (var openThing in thingRepository.Find(x => x.Status == Status.Open))
    CloseIt(openThing);

foreach (var negativeWhatsit in whatsitRepository.Find(x => x.Amount < 0))
    BePositive(negativeWhatsit);
var openThings = thingRepository.Find(x => x.Status == Status.Open);
var negativeWhatsits = whatsitRepository.Find(x => x.Amount < 0);

// both queries will be executed here in one round-trip to database
foreach (var openThing in openThings)
    CloseIt(openThing);

foreach (var negativeWhatsit in negativeWhatsits)
    BePositive(negativeWhatsit);