使用NHibernate从嵌套集合返回类

时间:2009-06-16 11:01:51

标签: nhibernate

杜曼:

class Action
    Products: IList of class ActionProducts: 
          Category: class Category
                Products: IList of class Product

现在,我想要这个:

 var products = from a in Session.Linq<Action>()
                from ap in a.Products
                from p in ap.Category.Products
                where a.Name == name
                select p;

这个Linq实际上可以工作但是:1。为所有表而不是仅产生选择2.产生左外连接,而不是内部3.查询上的Distinct()不起作用(尽管ToList()。Distinct( )工作)。

也可以使用SelectMany(a =&gt; a.Products).SelectMany(ap =&gt; ap.Category.Products),但它对当前的NHibernate.Linq根本不起作用。

所以我想使用ICriteria。但我看不出如何退货而不是行动?

 ICriteria criteria = Session.CreateCriteria(typeof(Action))
    .Add(Expression.Eq("Name", name))
    .CreateAlias("Products", "ap")
    .CreateAlias("ap.Category.Products", "p")
    .SomehowReturnMeOnly("p");

那我该怎么回事只能回答(“p”)?所以我可以做到

return criteria.List<Product>();

哪个会失败,因为ICriteria会选择Actions而不是Products?

我可能会考虑使用HQL,但实际上我并不喜欢字符串查询...例如,这里的HQL可以工作并生成我需要的SQL:

 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>();

3 个答案:

答案 0 :(得分:2)

现在,可以使用

完成类似的事情(记住CreateAlias只能做1级)
 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>();

这可以工作并通过测试,但会生成“SELECT FROM products WHERE id in(subquery)”,这可能更好(不需要DISTINCT)但不是我想要实现的。似乎Criteria API非常非常严格。所以我们有:

  1. 带有字符串查询缺陷的HQL
  2. Criteria API有很多限制,有时候代码很糟糕,无法实现简单的结果
  3. NH-Linq看起来很有前途,但现在还不完整。
  4. 所以我想在Linq准备好之前我会坚持使用HQL。

答案 1 :(得分:1)

您需要使用预测,如下所示:

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 docs here

答案 2 :(得分:0)

好吧,在考虑了克里斯的回答之后......我试过这个并且似乎有效:

 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")));

看起来NHibernate不允许深度嵌套投影属性,这很奇怪。并且它也不起作用,查看生成的SQL我发现它只选择

SELECT distinct c2_.Id as y0_ FROM ... Categories c2_ ...

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