- PVSM.RU - https://www.pvsm.ru -
То, о чем написано в статье, я отлавливал около 10 часов, это были 10 часов непрерывного дебага, которые cвелись к пошаговому сравнению рабочей и нерабочей версий кода, даже не так, к сравнению каждой строчки из окошка дебага рабочей и не рабочей версий кода
Для программиста, не знакомого с деревьями выражений хорошая вводная статья на msdn [1], в ней подробно раскрываются некоторые шаги в построении дерева, которые я опустил в статье.
В каком случае этот тест будет зеленым (включена надстройка EF, при которой он падает, если не может полностью транслировать запрос в SQL).
Во-вторых, провайдер должен разобрать этот маппинг, вот, такой, например, не пойдет, EF начнет ругаться (по умолчанию не ругается, поднимает сущности в память — LINQ to Object, но это можно включить [2]):
А все дело в том, что Query Provider не понимает по какому свойству(свойствам) сущности мы хотим сортировать. Но если маппинг написан правильно, то провайдер справится, отправит SQL запрос, получит ответ и десериализует результаты.
Иногда возникает необходимость написания Expression'ов самому, т.е что-то похожее:
Я покажу, как написать этот Expression, это не так сложно, по ссылке выше приводятся несколько похожих примеров:
Мы по шагам собираем лямбду, сначала параметр, свойство, а потом склеиваем все.
В каком случае это не будет работать и тест будет зеленым(провайдер не сможет разобрать expression)?
Не знаете? Не огорчайтесь, я тоже не знал, и в итоге потратил около 10 часов, чтобы понять.
Вот подсказка, так все будет работать:
Все дело в том, что PropertyInfo нужно брать из базового класса, если само свойство PupilName принадлежит базовому классу, так C# строит lambda expression, и EF разбирает их, полагаясь на стандарты языка
Что показывает debugger, если написать обычную лямбду в OrderBy:
А в нашем случае так:
Если вы старайтесь не дублировать код, то наверняка сталкивались с наследованием DTO и IncludeBase:
Бывает еще более изощренная ситуация:
И этот тест будет зеленым:
А дело в том же самом, снова PropertyInfo подтягивается из интерфейса:
ReflectedType свойства Age это интерфейс, IPupilDto, С# строит лямбду, в которой свойство Age — свойство класса PupilDto, а не интерфейса, а вот, как строит лямбду автомаппер:
Как же решить эту проблему? Если IncludeBase Automapper'a с интерфейсом нас не устраивает ( если вы используете маппинг в памяти — это вас не коснется), то придется отказаться от этого API, я решил эту проблему выделив маппинг в extension метод, вот так:
Тогда автомаппер сам найдет подходящее свойство типа по имени, построит "правильную" лямбду
Спасибо за внимание!
Автор: brager17
Источник [3]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/c-2/319020
Ссылки в тексте:
[1] хорошая вводная статья на msdn: https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/concepts/expression-trees/#creating-expression-trees-from-lambda-expressions
[2] включить: https://docs.microsoft.com/ru-ru/ef/core/querying/client-eval
[3] Источник: https://habr.com/ru/post/453720/?utm_campaign=453720
Нажмите здесь для печати.