LINQ to NHibernate - 如何检测失败的翻译

时间:2011-06-09 12:33:08

标签: linq nhibernate lambda

我正在编写一个(又一个)实体的通用存储库,它不一定由关系数据库支持。我希望其中一个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是否无法转换表达式,或者在不执行查询的情况下翻译表达式?

1 个答案:

答案 0 :(得分:3)

我认为没有,但由于NHibernate是一个开源项目,你可以轻松地这样做:

  1. 抓住NHibernate's source code
  2. 将LINQ提供程序中的所有NotSupportedException替换为更具体的异常(将继承NotSupportedException以避免不必要的破坏)
  3. 编译修改后的NHibernate并在代码中使用它。
  4. 在您的代码中随时随地处理新的异常。
  5. 将修改作为补丁提交给NHibernate JIRA(不要忘记测试,否则可能不会考虑)
  6. 利润!