使用NHibernate从嵌套集合返回类

使用NHibernate从嵌套集合返回类,nhibernate,Nhibernate,多曼: 现在,我想要这个: class Action Products: IList of class ActionProducts: Category: class Category Products: IList of class Product 那么我该怎么做呢?这样我就可以 ICriteria criteria = Session.CreateCriteria(typeof(Action)) .Add(Expres

多曼:

现在,我想要这个:

class Action
    Products: IList of class ActionProducts: 
          Category: class Category
                Products: IList of class Product
那么我该怎么做呢?这样我就可以

 ICriteria criteria = Session.CreateCriteria(typeof(Action))
    .Add(Expression.Eq("Name", name))
    .CreateAlias("Products", "ap")
    .CreateAlias("ap.Category.Products", "p")
    .SomehowReturnMeOnly("p");
返回条件.List();
哪个会失败,因为iCiteria选择的是行动,而不是产品

我可以考虑HQL,但实际上我不喜欢字符串查询…举个例子,下面是一个HQL,它可以工作并生成我所需要的SQL:

return criteria.List<Product>();
IQuery query=Session.CreateQuery(“从操作a内部连接a.Products作为ap内部连接ap.Category.Products作为p中选择不同的p”);
返回query.List();

您需要使用投影,如下所示:

 IQuery query = Session.CreateQuery("select distinct p from Action a inner join a.Products as ap inner join ap.Category.Products as p");
 return query.List<Product>();
ICriteria-criteria-criteria=Session.CreateCriteria(typeof(Action))
.Add(Expression.Eq(“Name”,Name))
.CreateAlias(“产品”、“ap”)
.CreateAlias(“ap.Category.Products”、“p”)
.SetProjection(Projections.Property(“ap.Category.Products”))
.List();

看看nhibernate文档中的一些例子。

好吧,在考虑了Chris的答案之后。。。我试过这个,它似乎奏效了:

ICriteria criteria = Session.CreateCriteria(typeof(Action))
    .Add(Expression.Eq("Name", name))
    .CreateAlias("Products", "ap")
    .CreateAlias("ap.Category.Products", "p")
    .SetProjection(Projections.Property("ap.Category.Products"))
    .List<Product>();
看起来NHibernate不允许投影属性的深度嵌套,这很奇怪。它也不起作用,查看生成的SQL,我发现它只选择

 ICriteria criteria = Session.CreateCriteria(typeof(Action))
    .Add(Expression.Eq("Name", name))
    .CreateAlias("Products", "ap")
    .CreateAlias("ap.Category", "c")
    .SetProjection(Projections.Distinct(Projections.Property("c.Products")));

i、 e.它并没有真正获取产品,这使得我的单元测试失败,因为返回的列表只包含null而不是产品实例。

现在,可以使用

DetachedCriteria dq=DetachedCriteria.For()
.Add(Expression.Eq(“Name”,Name))
.CreateAlias(“产品”、“ap”)
.CreateAlias(“ap.Category”、“c”)
.CreateAlias(“c.Products”、“p”)
.SetProjection(Projections.Property(“p.Id”));
ICriteria标准=Session.CreateCriteria(产品类型))
.Add(subquerys.PropertyIn(“Id”,dq));
返回条件。List();
这可以工作并通过测试,但会产生“从产品中选择id所在的位置(子查询)”,这可能会更好(不需要特别说明),但不是我想要实现的。似乎标准API是非常非常严格的。因此,我们:

  • 具有字符串查询缺陷的HQL
  • CriteriaAPI有很多限制,有时代码很糟糕,可以实现简单的结果
  • NH Linq看起来很有希望,但现在还不完整

  • 所以我想我会坚持使用HQL,直到Linq准备好。

    我在那里尝试了很多投影,还有投影列表,使用CreateCriteria而不是Alias。。。这一切都不起作用。以下是典型的异常(适用于您的代码):NHibernate.QueryException:无法解析属性:Category.Products of:OrderEntry3.Core.ActionProduct以下是结果相同的问题-空值而不是实例,而HQL工作正常:
     ICriteria criteria = Session.CreateCriteria(typeof(Action))
        .Add(Expression.Eq("Name", name))
        .CreateAlias("Products", "ap")
        .CreateAlias("ap.Category", "c")
        .SetProjection(Projections.Distinct(Projections.Property("c.Products")));
    
    SELECT distinct c2_.Id as y0_ FROM ... Categories c2_ ...
    
     DetachedCriteria dq = DetachedCriteria.For<Action>()
         .Add(Expression.Eq("Name", name))
         .CreateAlias("Products", "ap")
         .CreateAlias("ap.Category", "c")
         .CreateAlias("c.Products", "p")
         .SetProjection(Projections.Property("p.Id"));
      ICriteria criteria = Session.CreateCriteria(typeof(Product))
         .Add(Subqueries.PropertyIn("Id", dq));
      return criteria.List<Product>();