我正在编写一个(又一个)实体的通用存储库,它不一定由关系数据库支持。我希望其中一个IEnumerable<T> Load<T>(...)
方法作为参数使用通用Expression<Func<T, bool>>
谓词,该谓词为要检索的实体指定用户定义的标准。请注意,我不想向用户公开完整的IQueryable<T>
,因为我希望将底层存储的曝光限制在我的用户身上。
在NHibernate支持存储库的情况下(3.1,顺便说一句),简单的谓词 - 例如x => x.Name="Mike"
- 可以通过LINQ for 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 。为此,我尝试了在Does anyone know how to translate LINQ Expression to NHibernate HQL statement?中提出的解决方案,以便在执行之前转换查询,我不得不说我让它工作,但是它使用Reflection来访问未记录的,非公共的内部方法NHibernate对象,因此它闻起来像一个不受支持的黑客。
是否有更可靠和“官方”的方法来检测LINQ到NHibernate是否无法转换表达式,或者在不执行查询的情况下翻译表达式?
答案 0 :(得分:3)
我认为没有,但由于NHibernate是一个开源项目,你可以轻松地这样做:
NotSupportedException
替换为更具体的异常(将继承NotSupportedException
以避免不必要的破坏)