LINQ to NHibernate - Как обнаружить неудачный перевод - PullRequest
0 голосов
/ 09 июня 2011

Я пишу (еще один) универсальный репозиторий сущностей, который не обязательно поддерживается реляционной базой данных.Мне бы хотелось, чтобы один из методов IEnumerable<T> Load<T>(...) принял в качестве аргумента общий предикат Expression<Func<T, bool>>, который задает пользовательские критерии для извлечения сущностей.Обратите внимание, что я не хочу предоставлять пользователю полный IQueryable<T>, поскольку хочу ограничить доступ к базовому хранилищу для моих пользователей.

В тех случаях, когда хранилище поддерживается NHibernate.(Кстати, 3.1), простые предикаты - такие как x => x.Name="Mike" - могут быть «вытолкнуты» в реляционную базу данных с помощью LINQ для NHibernate (с использованием метода Where(Expression<Func<T, bool>>)) с очевидным приростом производительности, когда базовый набор объектовбольшой, и предикат выбирает только одну сущность.Ницца.

Однако мои пользователи не обязательно знают, что хранилище поддерживается реляционной базой данных, поэтому предикаты могут быть порой настолько сложными (например, x => MyFunction(x.Name) == 0), что LINQ to NHibernate не может генерировать HQL для них.В этих случаях я хотел бы обнаружить сбой LINQ при создании HQL и прозрачно «переключить» для загрузки всех сущностей и явного применения предиката к каждому.

Проблема в том, что я не могу найти способ надежного обнаружения этогоLINQ to NHibernate не может перевести выражение предиката.При немедленном выполнении запроса выдается System.NotSupportedException , которое может быть вызвано чем угодно, даже базовым ConnectionProvider .

На мгновение я развлекался возможностью разбить выполнение запроса на два - сначала выполнить преобразование, затем выполнить, а затем перехватить System.NotSupportedException во время перевода.С этой целью я попробовал решение, предложенное в Кто-нибудь знает, как перевести LINQ Expression в оператор NHibernate HQL? , чтобы перевести запрос перед выполнением, и я должен сказать, что заставил его работать,но он использует Reflection для доступа к недокументированным закрытым методам внутренних объектов NHibernate и, таким образом, пахнет как неподдерживаемый взлом.

Есть ли более надежный и "официальный" способ либо обнаружить, что LINQ to NHibernate не может перевести выражение, либо перевести выражение без выполнения запроса?

1 Ответ

3 голосов
/ 09 июня 2011

Я не думаю, что есть, но, поскольку NHibernate - проект с открытым исходным кодом, вы можете легко сделать это следующим образом:

  1. Grab Исходный код NHibernate .
  2. Заменить все NotSupportedException в поставщике LINQ более конкретным исключением (которое унаследует NotSupportedException, чтобы избежать ненужного взлома)
  3. Скомпилируйте ваш модифицированный NHibernate и используйте его в своем коде.
  4. Обрабатывайте новое исключение везде, где вам нужно в вашем коде.
  5. Отправьте свои изменения в виде патча для NHibernate JIRA (не забудьте тесты, иначе это, вероятно, не будет учитываться)
  6. Прибыль!
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...