没有这种事
每个人对 100% 实施的 LINQ 提供程序应具有的功能都有自己的定义。人们可能期望 LINQ 提供程序能够转换String.Equals(String, String, StringComparison)
为使用正确排序规则的 SQL 表达式,但除非创建 LINQ 提供程序的程序员将其编程为这样做,否则它将无法做到这一点。我们可能希望 LINQ 提供程序能够做的事情没有尽头,因此每个LINQ 提供程序都有限制。对于 LINQ 提供程序,没有 100% 这样的事情。这是一个高不可攀的概念。它是无限的。
因此,重要的是...
- 了解您的 LINQ 提供程序的限制,并且
- 知道如何解决这些限制。
限制
对于 NHibernate,了解限制比它应该做的要困难一些,因为目前没有 NHibernate LINQ 提供程序的官方文档。(NH-2444,欢迎使用补丁!)但是,您可以通过知道此 LINQ 提供程序构建在 HQL 之上来解决其中的一些问题,因此 HQL 具有的任何限制,LINQ 也将具有。
没有 NHibernate 查询语法直接支持在不相关的列上执行任意左外连接(当然,除了 Native SQL)。NHibernate 中的查询被设计成执行连接的所有信息都已经存储在映射中。之后,您所要做的就是指定关系,例如order.Customer
, NHibernate 知道哪些表和列连接在一起。您应该能够使用 HQL 或 LINQ 进行任意交叉连接,然后您可以添加 where 子句以使其表现得像内连接,但没有左外连接。
由于没有一个查询语法直接支持您想要执行的操作,因此构建一个 LINQ/QueryOver 包装器(与现有的 LINQ/HQL 包装器相对,并且可能与实现一样复杂)将一无所获。无论您使用的是 LINQ 还是 QueryOver,您都必须采取相同的步骤来处理此查询。
解决方法
由于 LINQ 提供程序不可能是完整的,因此设计良好的 LINQ 提供程序必须是可扩展的。这样,如果 LINQ 提供程序本身不支持您需要的功能,它不会毁了您的一天。NHibernate LINQ 提供程序可以扩展。有关更多信息,请参阅Giorgetti Alessandro 的博客。
但是,当然,在我们开始编写 LINQ 提供程序扩展之前,我们应该检查一下是否有更简单的方法来解决问题。我想到了几种可能性:
处理这个问题的最简单方法是简单地将关系添加到您的 NHibernate 映射中,使您能够在 NHibernate 查询(LINQ 或其他)中利用它。如果两列的数据类型不兼容,或者需要进行某种操作才能执行连接,请考虑修复数据和架构以实现更平滑的映射。
另一种选择是通过子查询获得创意或使用多个查询来模拟您想要的连接会做什么。例如,请参阅我的其他答案之一:
...这个 LEFT OUTER JOIN 可以通过组合两个单独查询的结果来模拟 - 一个来获取订单...
var orders = session.Query<OrderHeader>()
.Fetch(x => x.CreatedBy);
......还有另一个是为了让没有订单的人:
var peopleWithNoOrders = session.Query<Person>()
.Where(p => !session.Query<OrderHeader>().Any(o => o.CreatedBy == p));
...因为 aleft outer join
相当于inner join
加上不匹配的附加结果。我不知道您尝试执行的加入的详细信息,但希望这会给您提供足够的想法来开始。