【问题标题】:C# NHibernate root aggregate filtering child collection with subqueryC# NHibernate 根聚合过滤子集合与子查询
【发布时间】:2016-02-06 03:21:22
【问题描述】:

我正在尝试检索根元素列表及其子集合,在子集合中应用子查询过滤器。这个子查询需要带上根的子元素的最后一次出现。

预期的结果是一个根元素的列表,其中每个元素在子集合属性中只有其子元素的最后一次出现。

这些元素的类表示:

public class Root {
   public virtual long id { get; set; }
   public virtual ISet<Child> childList { get; set; }
}

public class Child {
   public virtual long id { get; set; }
   public virtual DateTime occurrence { get; set; }
   public virtual Root parent { get; set; }
}

我尝试使用 NHibernate 的 QueryOver 创建一个查询,不幸的是它没有按预期工作。

这是我尝试过的代码:

Root rootAlias = null;
Child childAlias = null;

var query = QueryOver.Of(() => rootAlias)
   .Left.JoinAlias(
      () => rootAlias.childList, 
      () => childAlias, 
      Restrictions.Where<Child>(
         cd => cd.occurrence == QueryOver.Of<Child>()
            .Where(cx => cx.parent.id == rootAlias.id)
            .Select(cx => cx.occurrence)
            .OrderBy(cx => cx.occurrence).Desc
            .Take(1)
            .As<DateTime>()
   )                    
);

如果你们能帮助我解决这个问题,我会很高兴,或者甚至指出另一种方法来达到上述结果。

【问题讨论】:

    标签: c# nhibernate


    【解决方案1】:

    在搜索和阅读了数百篇类似的帖子后,我找到了解决问题的方法。

    正如我在问题中所说:“预期的结果是一个根元素列表,其中每个元素在子集合属性上只有其子元素的最后一次出现。”

    这是考虑到我的类结构的解决方案:

    // Aliases
    Root rootAlias = null;
    Child x_temp = null;
    Child childAlias = null;
    
    // Result list.
    IList<Root> roots = null;
    
    // Subquery which retrieves a list of child's id by max occurrence and grouping by 
    // root id.
    var subquery = CurrentSession.QueryOver<Child>(() => x_temp)
        .SelectList(list => list
            .Select(() => x_temp.id)
            .SelectMax(() => x_temp.occurrence)
            .SelectGroup(() => x_temp.root.id)
        )
        .List<object[]>()
            .Select(p => p[0]).ToArray();
    
    // Query root elements, joining with child collection, applying
    // a restriction on child's id attribute through 
    // JoinAlias' "With clause" parameter.
    var query = QueryOver.Of(() => rootAlias).Left.JoinAlias(
        () => rootAlias.childList,
        () => childAlias,
        Restrictions.On(() => childAlias.id).IsIn(subquery)
    );
    
    // retrieves the final result list through the query.
    roots = query.GetExecutableQueryOver(CurrentSession).List();
    

    就是这样!

    我希望它对其他有类似问题的人有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      相关资源
      最近更新 更多