1

我一直在试图弄清楚为什么这个询问经理和他或她的团队的查询只返回团队集合的第一个条目。显然,这是因为我在查询末尾有 FirstOrDefault 。我的印象是 FirstOrDefault 将作为一个整体应用于查询,但似乎它也被应用于 Team 集合。

原始查询(仅显示团队中的第一个成员):

  session.Query<IEmployee>()
                .Where(p => p.PersonalNumber == PersonalNumber)
                .Fetch(p => p.Team)
                .Fetch(p => p.Manager)
                .FirstOrDefault();

返回完整团队的新查询:

  session.Query<IEmployee>()
                .Where(p => p.PersonalNumber == PersonalNumber)
                .Fetch(p => p.Team)
                .Fetch(p => p.Manager)
                .ToList().FirstOrDefault();

制定此查询的正确方法是什么?我需要解决方法意味着我没有正确执行此操作。

背景 - 映射:

这是一个基本的层次关系,Manager 是 IEmployee,Team 是 IEmployee 的 IList。

References(x => x.Manager).Column("ManagerId");
HasMany(x => x.Team)
                .AsList(index => index.Column("TeamIndex"))
                .KeyColumn("ManagerId");
4

3 回答 3

3
session.Query<IEmployee>()
            .Where(p => p.PersonalNumber == PersonalNumber)
            .Fetch(p => p.Team)
            .Fetch(p => p.Manager)
            .FirstOrDefault();

在此查询中,FirstOrDefault 按您的预期在数据库上工作。

session.Query<IEmployee>()
            .Where(p => p.PersonalNumber == PersonalNumber)
            .Fetch(p => p.Team)
            .Fetch(p => p.Manager)
            .ToList().FirstOrDefault();

在此查询中,ToList 对数据库起作用。All behind 对 ToList 的结果起作用。所以 FirstOrDefault 从 ToList 的结果集中获取 FirstOrDefault。要获得相同的结果,您需要在查询中添加订单。当您进行无顺序选择时,Sql 不会授予结果集的相同顺序。ToList 结果中的顺序与第一个查询中的内部顺序不同。

于 2012-05-02T08:30:06.663 回答
1

我一直在努力解决同样的问题。对我来说,这发生在从 NH 3.1 -> 3.3 升级时。问题在于,使用 Linq,NHibernate 3.3 会生成一个 SQL 查询,其中包含“Top(1)”语句,从而有效地终止了查询的“Fetch”部分。我通过从 Linq 切换到QueryOver解决了这个问题。我相信这会奏效:

  session.QueryOver<IEmployee>()
                .Where(p => p.PersonalNumber == PersonalNumber)
                .Fetch(p => p.Team)
                .Fetch(p => p.Manager)
                .SingleOrDefault();
于 2012-05-03T13:09:04.290 回答
0

问题是我要求笛卡尔积(使用 Fetch)但也使用 FirstOrDefault;从生成的 SQL 中,我可以看到该组合不起作用,因为您只能得到笛卡尔积的第一行(生成的 SQL:“FETCH NEXT 1 ROWS ONLY”)。

如果我想这样做,我将需要编写一种不同类型的查询,或者只使用 ToList 解决方法,在这种情况下不会造成太大的伤害,因为无论如何我只期望来自数据库的一个结果。

示例解决方案:

session.QueryOver<IEmployee>()
                .Where(p => p.PersonalNumber == PersonalNumber)
                .Fetch(p => p.Team).Eager
                .Fetch(p => p.Manager).Eager
                .SingleOrDefault();
于 2012-05-03T12:22:41.597 回答