我正在寻找几天前没有结果的答案。
我正在尝试使用NHibernate为通用存储库创建一个IRepository接口的实现。这是界面:
public interface IRepository<TEntity, TKey> where TEntity : BaseEntity
{
TEntity GetById(TKey id);
void Insert(TEntity entidad);
void Update(TEntity entidad);
void Delete(TEntity entidad);
IQueryable<TEntity > Table { get; };
}
我知道ISession接口有一个扩展,它在我的查询中使用LINQ,但我也知道该插件不能100%工作(我测试了它但是当我尝试执行一些时复杂的查询,它没有实现异常,所以我不能使用那个插件)
我正在使用来自ISession的100%QueryOver函数,所以..你知道如何将IQueroOver函数实现为IQueryable(不启动“SELECT *”查询)吗?如果没有,那么在没有使用LINQ扩展的情况下实现通用存储库模式的任何其他想法?
非常感谢
答案 0 :(得分:1)
每个人都有自己定义100%实现的LINQ提供程序应具有的功能。
有人可能希望LINQ提供程序能够将String.Equals(String, String, StringComparison)
转换为使用正确排序规则的SQL表达式,但除非创建LINQ提供程序的程序员对其进行编程,否则它将无法执行此操作。 。
我们可能希望LINQ提供商能够做到的事情没有尽头,所以每个 LINQ提供商都有局限性。
在LINQ提供商方面,没有100%这样的东西。
这是一个无法实现的概念。
这是无限的。
因此,重要的是......
使用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's blog。
但是,当然,在我们编写LINQ提供程序扩展之前,我们应该检查是否有更简单的方法来解决问题。 想到了几种可能性:
处理此问题的最简单方法是简单地将关系添加到NHibernate映射,使您能够在NHibernate查询(LINQ或其他)中利用它。 如果这两列是不兼容的数据类型,或者在执行连接之前需要某种操作,请考虑修复数据和模式,以便实现更平滑的映射。
另一种选择是通过子查询获得创意,或使用多个查询来模拟您所需的联接将执行的操作。例如,请参阅我的other answers之一:
...这个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));
...因为left outer join
相当于inner join
加上非匹配的附加结果。我不知道您尝试执行的联接的详细信息,但希望这会给您足够的想法以便开始。