如何使用NHibernate的QueryOver API表达包含WHERE..IN子查询的查询?

时间:2012-12-21 18:23:14

标签: c# nhibernate queryover

我有一个对象模型,Order包含许多LineItems,每个LineItem都有一个关联的Product。在对象模型中,这些是单向关联 - LineItemOrder一无所知。

Class diagram

我想查询包含产品名称与字符串匹配的订单项的订单,为每个订单返回一行(以便可以执行分页)。

SELECT * FROM Orders 
WHERE OrderID IN (
    SELECT DISTINCT OrderID 
    FROM LineItems 
    INNER JOIN Products on LineItems.ProductID = Products.ProductID
    WHERE Products.Name = 'foo'
)

鉴于我有一个代表子查询的ICriteriaIQueryOver,我如何将其实际应用于我的根订单查询?

var subquery = QueryOver.Of<LineItem>
                        .Where(l => l.Product.Name == "foo")
                        .TransformUsing(Transformers.DistinctRootEntity);

我发现很多例子假设查询中的根对象是在一对多关系的“多”方面,但我无法弄清楚如何在某些东西上添加限制root对象有很多

2 个答案:

答案 0 :(得分:2)

您可以使用此

直接翻译您提供的SQL
var subQuery = 
      QueryOver.Of<LineItem>(() => lineItem)
            .JoinAlias(() => lineItem.Products, () => product)
            .Where(() => product.Name == "foo")
            .Select(Projections.Distinct(
                      Projections.Property(()=> lineItem.Order.Id)));;

var theQueryYouNeed =  
               QueryOver.Of<Orders>(() => order)
              .WithSubquery.WherePropertyIn(() => order.Id).In(subQuery); 

但是,如果您的LineItem实体没有Order属性,那么您无法真正使用子查询。

如果你需要找到

所有具有LineItem的订单,其中产品名称为“foo”,然后

var theQueryYouNeed = 
  QueryOver.Of<Orders>(() => order)
     .JoinAlias(() => order.LineItems, () => lineItem)
     .JoinAlias(() => lineItem.Product, () => product)
     .Where(() => product.Name == "foo")
     .TransformUsing(new DistinctRootEntityResultTransformer())

答案 1 :(得分:2)

我会在订单和订单项之间建立双向关系,以便进行有效查询(减少所需的连接数)。但是,如果由于某种奇怪的原因你不能,你需要从订单中启动子查询...

LineItem lineItemAlias = null;
Product productAlias = null;

var subQuery = QueryOver.Of<Order>()
            .JoinAlias(x => x.LineItems, () => lineItemAlias)
            .JoinAlias(() => lineItemAlias.Product, () => productAlias)
            .Where(() => productAlias.Name == "foo")
            .Select(Projections.Group<Order>(x => x.Id));

var results = Session.QueryOver<Order>()
              .WithSubquery.WhereProperty(x => x.Id).In(subQuery)
              .List();