如何在NHibernate中查询每个组中的第一个条目

How to query the first entry in each group in NHibernate

以下代码在 NHibernate 中使用 LINQ returns 与内存中 LINQ 和 EF LINQ 不同的结果。在 NHibernate 中执行此操作的正确方法是什么?如果LINQ版本确实坏了,用QueryOver就好了。

using (var session = factory.OpenSession())
using (var transaction = session.BeginTransaction())
{
    for (int i = 0; i < 10; ++i)
    {
        session.Save(new A()
        {
            X = i % 2,
            Y = i / 2,
        });
    }
    transaction.Commit();
}
using (var session = factory.OpenSession())
using (var transaction = session.BeginTransaction())
{
    //=====================================
    var expected = session.Query<A>()
        .ToList() // <-- copy to memory
        .GroupBy(a => a.X)
        .Select(g => g.OrderBy(y => y.Y).First())
        .ToList();
    Console.WriteLine(string.Join(" ", expected.Select(a => a.Id)));
    //=====================================
    var actual = session.Query<A>()
        .GroupBy(a => a.X)
        .Select(g => g.OrderBy(y => y.Y).First())
        .ToList();
    Console.WriteLine(string.Join(" ", actual.Select(a => a.Id)));
}

public class A
{
    public int Id { get; set; }
    public int X { get; set; } // indexed
    public int Y { get; set; } // indexed
}

预期结果

1 2

实际结果

1 1

记录SQL

NHibernate: select (select program_a0_.Id as id1_0_ from "A" program_a0_ order by program_a0_.Y asc limit 1) as col_0_0_ from "A" program_a0_ group by program_a0_.X

完整代码在错误报告中Incorrect result when using GroupBy with First


2019-8-9更新

查询不应使用 ID。我已将其更改为非唯一 属性。如果解决方案只查询一次SQLite.

,我将不胜感激

似乎最新的 NHibernate 5.3 LINQ 提供程序在 Select 中仅支持聚合函数(MIN、MAX、COUNT...)用于“分组依据”查询。分组查询不支持实体 select。

作为一般解决方案,您可以使用以下方法使用子查询重写“分组依据”查询:

var results = session.Query<A>()
     .Where(a => a == session.Query<A>() // Subquery on same entity
                         .Where(sa => sa.X == a.X) // Group BY key is here
                         .OrderBy(sa => sa.Y) // Order By key is here
                         .First() // First entry in group
     ).ToList();

原“分组依据”查询供参考:

var results = session.Query<A>()
    .GroupBy(a => a.X)
    .Select(g => g.OrderBy(y => y.Y).First())
    .ToList();