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, которые предназначены для любой выборки, но Я понятия не имею, возможно ли это и насколько уродливо это было бы. Я ищу некоторые альтернативы, которые могут позволить получить желаемое поведение, минуя ограничение на то, как работает выборка. Есть какие-нибудь мысли?

589   1  

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

    Ничего не найдено.