为什么这两个流畅的nHibernate查询会产生不同的结果?

为什么这两个流畅的nHibernate查询会产生不同的结果?,nhibernate,fluent-nhibernate,fluent-nhibernate-mapping,Nhibernate,Fluent Nhibernate,Fluent Nhibernate Mapping,我一直在试图弄清楚,为什么这个询问经理及其团队的查询只返回团队集合的第一个条目。显然,这是因为我在查询结束时有FirstOrDefault。我的印象是FirstOrDefault将应用于整个查询,但它似乎也应用于团队集合 原始查询(仅显示团队中的第一名成员): session.Query() .其中(p=>p.PersonalNumber==PersonalNumber) .Fetch(p=>p.Team) .Fetch(p=>p.Manager) .FirstOrDefault(); 在这个

我一直在试图弄清楚,为什么这个询问经理及其团队的查询只返回团队集合的第一个条目。显然,这是因为我在查询结束时有FirstOrDefault。我的印象是FirstOrDefault将应用于整个查询,但它似乎也应用于团队集合

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

session.Query()
.其中(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();
session.Query()
.其中(p=>p.PersonalNumber==PersonalNumber)
.Fetch(p=>p.Team)
.Fetch(p=>p.Manager)
.ToList().FirstOrDefault();
在这个查询中,ToList作用于数据库。所有的幕后工作都是基于托利斯特的结果。因此FirstOrDefault从ToList的结果集中获取FirstOrDefault。要获得相同的结果,您需要向查询中添加订单。在执行无顺序选择时,Sql不会授予结果集的相同顺序。ToList结果中的顺序与第一次查询中的内部顺序不同。

session.query()
.其中(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();
session.Query()
.其中(p=>p.PersonalNumber==PersonalNumber)
.Fetch(p=>p.Team)
.Fetch(p=>p.Manager)
.ToList().FirstOrDefault();

在这个查询中,ToList作用于数据库。所有的幕后工作都是基于托利斯特的结果。因此FirstOrDefault从ToList的结果集中获取FirstOrDefault。要获得相同的结果,您需要向查询中添加订单。在执行无顺序选择时,Sql不会授予结果集的相同顺序。ToList结果中的顺序与第一次查询中的内部顺序不同。

问题是我要求的是笛卡尔乘积(使用Fetch),但也使用FirstOrDefault;从生成的SQL中,我可以看到这种组合不起作用,因为您只得到笛卡尔乘积的第一行(SQL生成:“仅获取下一行”)

如果我想这样做,我将需要编写一种不同类型的查询,或者只使用ToList解决方案,在本例中,这不会造成太大的伤害,因为我只希望从数据库中得到一个结果

示例解决方案:

session.QueryOver<IEmployee>()
                .Where(p => p.PersonalNumber == PersonalNumber)
                .Fetch(p => p.Team).Eager
                .Fetch(p => p.Manager).Eager
                .SingleOrDefault();
session.QueryOver()
.其中(p=>p.PersonalNumber==PersonalNumber)
.Fetch(p=>p.Team)。渴望
.Fetch(p=>p.Manager)
.SingleOrDefault();

问题在于,我要求的是笛卡尔乘积(使用Fetch),但也使用FirstOrDefault;从生成的SQL中,我可以看到这种组合不起作用,因为您只得到笛卡尔乘积的第一行(SQL生成:“仅获取下一行”)

如果我想这样做,我将需要编写一种不同类型的查询,或者只使用ToList解决方案,在本例中,这不会造成太大的伤害,因为我只希望从数据库中得到一个结果

示例解决方案:

session.QueryOver<IEmployee>()
                .Where(p => p.PersonalNumber == PersonalNumber)
                .Fetch(p => p.Team).Eager
                .Fetch(p => p.Manager).Eager
                .SingleOrDefault();
session.QueryOver()
.其中(p=>p.PersonalNumber==PersonalNumber)
.Fetch(p=>p.Team)。渴望
.Fetch(p=>p.Manager)
.SingleOrDefault();

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

  session.QueryOver<IEmployee>()
                .Where(p => p.PersonalNumber == PersonalNumber)
                .Fetch(p => p.Team)
                .Fetch(p => p.Manager)
                .SingleOrDefault();
session.QueryOver()
.其中(p=>p.PersonalNumber==PersonalNumber)
.Fetch(p=>p.Team)
.Fetch(p=>p.Manager)
.SingleOrDefault();

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

  session.QueryOver<IEmployee>()
                .Where(p => p.PersonalNumber == PersonalNumber)
                .Fetch(p => p.Team)
                .Fetch(p => p.Manager)
                .SingleOrDefault();
session.QueryOver()
.其中(p=>p.PersonalNumber==PersonalNumber)
.Fetch(p=>p.Team)
.Fetch(p=>p.Manager)
.SingleOrDefault();

对不起,我不太明白。结果集的顺序(始终只包含1个IEEmployee,PersonalNumber是唯一的)如何影响Employee.Team集合中的项目数?抱歉,我不太明白。结果集的顺序(始终只包含1个IEEMPLOYEE,PersonalNumber是唯一的)将如何影响Employee.Team集合中的项目数?您可以从生成的SQL中看出这是如何发生的,因为问题查询生成SQL“仅获取下一行”这可能意味着只会返回第一条连接记录。我不清楚的是如何让FirstOrDefault正确使用Fetch。您可以从生成的SQL中看出这是如何发生的,因为问题查询生成SQL“仅Fetch NEXT 1 ROWS ONLY”,这可能意味着只返回第一条连接记录。我不清楚的是如何让FirstOrDefault正确地使用Fetch。有趣的是,这也是我在一些实验后发现的(见下面的答案),是的,我正在使用nHibernate 3.3。我想知道是否应该使用原始语法
  session.QueryOver<IEmployee>()
                .Where(p => p.PersonalNumber == PersonalNumber)
                .Fetch(p => p.Team)
                .Fetch(p => p.Manager)
                .SingleOrDefault();