Ответ 1
Трудность использования фьючерсов с LINQ заключается в том, что операции, подобные Count, выполняются немедленно.
Как выяснил @vandalo, Count()
после ToFuture()
фактически запускает Count в памяти, что плохо.
Единственный способ получить счет в будущем запросе LINQ - использовать GroupBy
в инвариантном поле. Хорошим выбором будет то, что уже является частью ваших фильтров (например, свойство IsActive)
Вот пример, предполагающий, что у вас есть такое свойство в платеже:
//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, который полезен, когда вы хотите выполнить подкачку на уровне более высокого уровня:
//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-02-22): я написал сообщение в блоге об этой проблеме и гораздо лучшем решении.