NHibernate & LINQ: использование Fetch () с пользовательским методом ToPagedList
У меня есть проблема с использованием метода nHibernate Fetch() (или FetchMany()) с моим методом подкачки, который использует фьючерсы для получения необходимой информации. И я не знаю, как это исправить, но я точно знаю, что он делает. Позвольте мне объяснить, что у меня есть до сих пор.
Я использую метод расширения, найденный здесь, чтобы получить число строк в качестве будущего значения. это выглядит так.
public static IFutureValue<TResult> ToFutureValue<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<IQueryable<TSource>, TResult>> selector) where TResult : struct
{
var provider = (NhQueryProvider)source.Provider;
var method = ((MethodCallExpression)selector.Body).Method;
var expression = Expression.Call(null, method, source.Expression);
return (IFutureValue<TResult>)provider.ExecuteFuture(expression);
}
Это отлично работает, используя это, я могу затем объединить получение количества строк и получение моего результирующего набора в метод подкачки signle, который генерирует только один хит базы данных. Мой метод подкачки выглядит следующим образом.
public static IList<T> ToPagedList<T>(this IQueryable<T> query, int pageIndex, int pageSize, out int count)
{
var futureCount = query.ToFutureValue(x => x.Count());
var futureResults = pageIndex == 0 && pageSize == 0 ? query.ToFuture() : query.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToFuture();
count = futureCount.Value;
return futureResults.ToList();
}
С этим на месте я могу сделать запросы, подобные следующим.
repositoryInstance.Query().Where(x=>x.SomeTextField.Contains("lake")).ToPagedList(pageIndex, pageSize, out count);
Это работает как заклинание. Однако теперь мне нужно уметь определять определенные отношения как нетерпеливо загруженные, в этом случае это может выглядеть так.
repositoryInstance.Query().Where(x=>x.SomeTextField.Contains("lake")).FetchMany(x=>x.Details).ToPagedList(pageIndex, pageSize, out count);
Это взрывается с QueryException с описанием " Query specified join fetching, но владелец извлеченной ассоциации был нет в списке выбора". Причина этого заключается в том, что мой метод подкачки пытается применить агрегатный счетчик строк к запросу, в котором есть Fetch (), и вы не можете этого сделать, потому что ошибка правильная. Владельца извлеченной ассоциации не было в списке выбора (по крайней мере, его нет ни в одном из них), мой выбор по существу для первого запроса-это одно целое число. Я подумал, что, возможно, я мог бы вырвать узлы выражения один раз в ToPagedList, которые предназначены для любой выборки, но Я понятия не имею, возможно ли это и насколько уродливо это было бы. Я ищу некоторые альтернативы, которые могут позволить получить желаемое поведение, минуя ограничение на то, как работает выборка. Есть какие-нибудь мысли?
1 ответ:
Вы можете изменить ToPagedList следующим образом:
public static IList<T> ToPagedList<T>(this IQueryable<T> query, int pageIndex, int pageSize, out int count, Func<IQueryable<T>, IQueryable<T>> filterResult) { var futureCount = query.ToFutureValue(x => x.Count()); //change only the results query, not the count one if (customAction != null) query = filterResult(query); var futureResults = pageIndex == 0 && pageSize == 0 ? query.ToFuture() : query.Skip((pageIndex - 1) * pageSize) .Take(pageSize).ToFuture(); count = futureCount.Value; return futureResults.ToList(); }И использовать его так:
Я знаю, что это немного менее элегантно, но это будет работать, и это намного проще, чем изменять существующее выражение.repositoryInstance.Query().Where(x => x.SomeTextField.Contains("lake")) .ToPagedList(pageIndex, pageSize, out count, q => q.FetchMany(x => x.Details));
Comments