我在下面的方法中查询数据库以获取用户,订单或任何实体。我想知道下面的查询是否是最优的,还是我必须调整它。
只有在将所有记录存储在内存中后,查询才会执行操作吗?
我有没有办法为过滤而不是Expression
指定Func<>
?
获取Count的最佳方法是什么,指定条件/没有大量内存消耗的地方?
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();
}
答案 0 :(得分:2)
您需要解决几件事:
Expression
,而不是Func
您的Find
方法指定它需要Func
。如果你想要Expression
,你必须这样说:
public IList<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
QueryOver
代替ICriteria
假设您没有使用没有LINQ或QueryOver 的古老版本的NHibernate(奇怪的是,有很多人仍在使用NHibernate 1.2.1 - 我无法弄清楚原因)< / EM> ...
ICriteria
无法理解Expression
。将CreateCriteria(typeof(TEntity))
替换为Query<TEntity>()
或QueryOver<TEntity>()
,具体取决于您偏好的查询语法。
Where
应该在Future
您需要在Where
之前移动Future
。 Future
用于将多个查询一起批处理,以便在代码尝试评估其中一个“Future”查询的结果时,它们都会在数据库的一次往返中执行。在上面的代码调用Future
时,查询只包含CreateCriteria(typeof(TEntity))
,它只是告诉它要查询哪个表,如下所示:
select * from TEntity
如果你想在那里使用where子句,你必须切换这些方法调用:
filterCriterea.Where(predicate).Future<TEntity>()
这应该给你一个SQL查询,如:
select * from TEntity where ...
了解IQueryable
和IEnumerable
之间的区别非常重要。您应该注意到Query
会返回IQueryable
,而{ {1}}返回Future
。使用IEnumerable
操作IQueryable
将导致对执行的SQL进行更改。使用Expression
操纵IEnumerable
只会改变您查看内存数据的方式。
Func
取消ToList
Future
Future
遍历传递给它的集合,并将每个元素放在一个列表中。迭代集合的行为将导致Future查询立即执行,而不是让您有机会将其与其他查询一起批处理。如果必须有一个列表,您应该省略ToList
。但是,我认为更改方法以返回Future
会更好,这样您就可以将此查询与其他查询一起批处理。像这样......
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);