Я пишу (еще один) универсальный репозиторий сущностей, который не обязательно поддерживается реляционной базой данных.Мне бы хотелось, чтобы один из методов 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 не может перевести выражение, либо перевести выражение без выполнения запроса?