Linq to NHibernate и Dynamic LINQ - кеширование запросов не работает

У меня проблема с кешем второго уровня NHibernate. Когда я использую запрос:

        var items1 = Session.Query<Row>()
            .Cacheable();
            .Fetch(x => x.Field)
            .OrderBy(x => x.Field.Value)
            .ToList();

Все хорошо - запрос кешируется. Но когда я хочу использовать Dynamic Linq ( ссылка):

       var items2 = Session.Query<Row>()
            .Cacheable();
            .Fetch(x => x.Field)
            .OrderBy("Field.Value")
            .ToList();

Запрос не кэшируется. Интересно то, что когда я удаляю строку кода:

            .Fetch(x => x.Field)

кеширование снова работает Таким образом, проблема заключается в совместном использовании методов Fetch и динамического linq OrderBy.

РЕДАКТИРОВАТЬ:

Когда я пытаюсь выполнить отладку кода NH (класс QueryKey), отладчик говорит мне, что эти два запроса не имеют один и тот же ResultTransformer (и глубже: частный экземпляр listTransformation).

Есть идеи?

Крис

1 ответ

Решение

Хорошо, я знаю, в чем причина.

Динамический Linq не использует имена параметров в выражениях Linq. Например, если я хочу отсортировать с помощью лямбда-состояний, я пишу:

query.OrderBy(item => item.Name)

Выше мы видим item имя лямбда-параметра.

Когда я использую Dynamic LINQ:

query.OrderBy("Name")

в результате Queryable лямбда-параметр в методе OrderBy не имеет имени (например, item написано выше). Мы можем проиллюстрировать результат следующим образом:

query.OrderBy( => .Name)

И теперь, когда NHibernate декодирует это выражение Queryable и находит там параметр выражения, который не имеет имени, NH дает ему случайное имя, используя класс GUID. Таким образом, каждое упорядочение с использованием динамического linq создает выражение Queryable Expression, которое имеет непостоянный параметр лямбда Именно поэтому NHibernate считает, что: query.OrderBy("Name") а также query.OrderBy("Name") не одинаковы - у них есть другие параметры лямда, генерируемые каждый раз с нуля.

РЕШЕНИЕ

Если вы хотите это исправить, вы должны изменить библиотеку Dynamic Linq.

  1. В методе ExpressionParser.ProcessParameters изменить строку:

    if (parameters.Length == 1 && String.IsNullOrEmpty(parameters[0].Name))
    

    чтобы:

    if (parameters.Length == 1 && (parameters[0].Name == "it" || String.IsNullOrEmpty(parameters[0].Name)))
    
  2. В методе DynamicQueryable.OrderBy изменить строку:

    Expression.Parameter(source.ElementType, "")
    

    чтобы:

    Expression.Parameter(source.ElementType, "it")
    

Сейчас, query.OrderBy("Name") будет производить query.OrderBy(it => it.Name),

Ура!

Другие вопросы по тегам