NHibernate Futures使用Linq查询计数

时间:2013-10-04 06:32:44

标签: c# sql linq nhibernate

我在下面的方法中查询数据库以获取用户,订单或任何实体。我想知道下面的查询是否是最优的,还是我必须调整它。

只有在将所有记录存储在内存中后,查询才会执行操作吗?

我有没有办法为过滤而不是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();
}

1 个答案:

答案 0 :(得分:2)

您需要解决几件事:

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 - 我无法弄清楚原因)< / EM> ...

ICriteria无法理解Expression。将CreateCriteria(typeof(TEntity))替换为Query<TEntity>()QueryOver<TEntity>(),具体取决于您偏好的查询语法。

3。 Where应该在Future

之前

您需要在Where之前移动FutureFuture用于将多个查询一起批处理,以便在代码尝试评估其中一个“Future”查询的结果时,它们都会在数据库的一次往返中执行。在上面的代码调用Future时,查询只包含CreateCriteria(typeof(TEntity)),它只是告诉它要查询哪个表,如下所示:

select * from TEntity

如果你想在那里使用where子句,你必须切换这些方法调用:

filterCriterea.Where(predicate).Future<TEntity>()

这应该给你一个SQL查询,如:

select * from TEntity where ...

了解IQueryableIEnumerable之间的区别非常重要。您应该注意到Query会返回IQueryable,而{ {1}}返回Future。使用IEnumerable操作IQueryable将导致对执行的SQL进行更改。使用Expression操纵IEnumerable只会改变您查看内存数据的方式。

4。在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);