您需要修复以下几件事:
1. 要求一个Expression
,而不是一个Func
您的Find
方法指定它需要一个Func
. 如果你想要一个Expression
,你必须这样说:
public IList<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
2. 使用 LINQ 或QueryOver
代替ICriteria
假设您没有使用没有 LINQ 或 QueryOver 的旧版 NHibernate (奇怪的是,还有很多人仍在使用 NHibernate 1.2.1 - 我不知道为什么) ......
ICriteria
不明白Expression
s。替换CreateCriteria(typeof(TEntity))
为Query<TEntity>()
或QueryOver<TEntity>()
取决于您喜欢的查询语法。
3.Where
应该先去Future
您需要Where
在Future
. Future
用于将多个查询批处理在一起,以便在您的代码尝试评估“未来”查询之一的结果时,它们都会在一次往返数据库中执行。在您上面的代码调用Future
时,查询仅包含CreateCriteria(typeof(TEntity))
,它只是告诉它要查询哪个表,如下所示:
select * from TEntity
如果你想要一个 where 子句,你必须切换这些方法调用:
filterCriterea.Where(predicate).Future<TEntity>()
这应该给你一个 SQL 查询,如:
select * from TEntity where ...
IQueryable
了解和之间的区别非常重要IEnumerable
。 你应该注意到Query
返回一个IQueryable
,而Future
返回一个IEnumerable
。操作IQueryable
usingExpression
会导致执行的 SQL 发生变化。IEnumerable
使用 a操作Func
会改变您查看内存数据的方式。
4.ToList
立即Future
否定利益后Future
ToList
遍历传递给它的集合并将每个元素放入列表中。遍历集合的行为将导致 Future 查询立即执行,而不给您任何机会将它与其他查询一起批处理。如果你必须有一个列表,你应该省略Future
. 但是,我认为,将您的方法更改为返回 an 会是一个更好的主意IEnumerable
,这将使您能够将此查询与其他查询一起批处理。像这样...
public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
{
var query = _unitOfWork.CurrentSession.Query<TEntity>();
return query.Where(predicate).Future<TEntity>();
}
为了利用查询批处理,您可能必须重新排列调用此Find
方法的代码。例如,而不是...
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);