通过NHibernate + Linq + Future获得计数 [英] Getting count with NHibernate + Linq + Future

查看:55
本文介绍了通过NHibernate + Linq + Future获得计数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在编写Linq查询时使用NHibernate进行分页.做这样的事情很容易:

I want to do paging with NHibernate when writing a Linq query. It's easy to do something like this:

return session.Query<Payment>()
    .OrderByDescending(payment => payment.Created)
    .Skip((page - 1)*pageSize)
    .Take(pageSize)
    .ToArray();

但是,我没有得到有关物品总数的任何信息.而且,如果我只是执行一个简单的.Count(),那将生成对数据库的新调用.

But with this I don't get any info about the total number of items. And if I just do a simple .Count(), that will generate a new call to the database.

我找到了此答案,此问题得以解决通过使用未来.但是它使用标准.我如何用Linq做到这一点?

I found this answer which solved it by using future. But it uses Criteria. How can I do this with Linq?

推荐答案

将Futures与LINQ结合使用的困难在于,像Count这样的操作会立即执行.

The difficulty with using Futures with LINQ is that operations like Count execute immediately.

@vandalo发现,ToFuture()之后的Count()实际上在内存中运行计数,这很糟糕.

As @vandalo found out, Count() after ToFuture() actually runs the Count in memory, which is bad.

在将来的LINQ查询中获取计数的唯一方法是在不变字段中使用GroupBy.一个不错的选择是已经包含在您的过滤器中的内容(例如"IsActive"属性)

The only way to get the count in a future LINQ query is to use GroupBy in an invariant field. A good choice would be something that is already part of your filters (like an "IsActive" property)

下面是一个示例,假设您在付款"中拥有这样的属性:

Here's an example assuming you have such a property in Payment:

//Create base query. Filters should be specified here.
var query = session.Query<Payment>().Where(x => x.IsActive == 1);
//Create a sorted, paged, future query,
//that will execute together with other statements
var futureResults = query.OrderByDescending(payment => payment.Created)
                         .Skip((page - 1) * pageSize)
                         .Take(pageSize)
                         .ToFuture();
//Create a Count future query based on the original one.
//The paged query will be sent to the server in the same roundtrip.
var futureCount = query.GroupBy(x => x.IsActive)
                       .Select(x => x.Count())
                       .ToFutureValue();
//Get the results.
var results = futureResults.ToArray();
var count = futureCount.Value;

当然,另一种方法是进行两次往返,这还算不错.您仍然可以重用原始的IQueryable,当您想在更高层次的页面中进行分页时,这很有用:

Of course, the alternative is doing two roundtrips, which is not that bad anyway. You can still reuse the original IQueryable, which is useful when you want to do paging in a higher-level layer:

//Create base query. Filters should be specified here.
var query = session.Query<Payment>();
//Create a sorted, paged query,
var pagedQuery = query.OrderByDescending(payment => payment.Created)
                      .Skip((page - 1) * pageSize)
                      .Take(pageSize);
//Get the count from the original query
var count = query.Count();
//Get the results.
var results = pagedQuery.ToArray();

更新(2011年2月22日):我写了

Update (2011-02-22): I wrote a blog post about this issue and a much better solution.

这篇关于通过NHibernate + Linq + Future获得计数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆