LINQ to NHibernate - How to detect failed translation
I'm writing a (yet another) generic repository of entities, which is not necessarily backed by a relational database. I'd like one of the IEnumerable<T> Load<T>(...)
methods 开发者_如何学Pythonto take as argument a generic Expression<Func<T, bool>>
predicate that specifies user-defined criteria for the entities to retrieve. Please note that I don't want to expose a full IQueryable<T>
to the user as I want to limit the exposure of the underlying storage to my users.
In those cases in which the repository is backed by NHibernate (3.1, by the way), simple predicates - such as x => x.Name="Mike"
- can be "pushed down" to the relational database by LINQ for NHibernate (using the Where(Expression<Func<T, bool>>)
method), with obvious performance gains when the underlying set of entities is large and the predicate only selects one entity. Nice.
However, my users do not necessarily know that the repository is backed by a relational database, so the predicates can be at times so complex (e.g. x => MyFunction(x.Name) == 0
) that LINQ to NHibernate fails to generate HQL for them. In these cases I'd like to detect LINQ's failure to generate HQL and transparently "failover" to loading all entities and explicitly applying the predicate to each.
The problem is that I cannot find a way to reliably detect that LINQ to NHibernate fails to translate the predicate expression. Executing the query straight away throws a System.NotSupportedException which could be caused by anything, even by an underlying ConnectionProvider.
I entertained for a moment the possibility of breaking up the query execution in two - first translate, then execute - and then catch the System.NotSupportedException during translation. To this end, I tried the solution proposed in Does anyone know how to translate LINQ Expression to NHibernate HQL statement? in order to translate the query before execution, and I have to say that I got it to work, but it uses Reflection to access undocumented, non-public methods of internal NHibernate objects, and thus it smells like an unsupported hack.
Is there a more reliable and "official" way to either detect that LINQ to NHibernate fails to translate an expression, or to translate the expression without executing the query?
I don't think there is, but since NHibernate is an open source project you can easily do it like this:
- Grab NHibernate's source code.
- Replace all
NotSupportedException
in the LINQ provider with a more specific exception (which would inheritNotSupportedException
to avoid unnecessary breaking) - Compile your modified NHibernate and use it in your code.
- Handle the new exception wherever/however you need it in your code.
- Submit your modifications as a patch to the NHibernate JIRA (don't forget the tests, otherwise it probably won't be considered)
- Profit!
精彩评论