我有两个相关实体:作业和群组,多对多关系。
我正在执行一个简单的查询来检索特定的作业及其关联的组(通过 GroupRecipients 属性):
var job = jobsRepo.Get()
.Where(j => j.Id == jobKey.Id)
.FirstOrDefault();
var countA = job.GroupRecipients.Count;
结果是 countA == 2 ,它对应于数据库中的状态。
添加FetchMany时出现了第一个怪异:
var job = jobsRepo.Get()
.FetchMany(x => x.GroupRecipients)
.Where(j => j.Id == jobKey.Id)
.FirstOrDefault();
var countB = job.GroupRecipients.Count;
这导致 countB == 1 。 job.GroupRecipients集合中只显示一个项目,该项目与数据库中的状态相矛盾。
但它变得更有趣了。如果我连续运行以下内容:
var job = jobsRepo.Get()
.Where(j => j.Id == jobKey.Id)
.FirstOrDefault();
var countA = job.GroupRecipients.Count;
var jobB = jobsRepo.Get()
.FetchMany(x => x.GroupRecipients)
.Where(j => j.Id == jobKey.Id)
.FirstOrDefault();
var countB = jobB.GroupRecipients.Count;
然后我得到 countB == 2 ,预期的结果。再次使用countA删除该行会导致 countB == 1 。
更多信息: 我在无状态会话中的交易中执行查询。 NHibernate的版本是 3.3.1
这两个问题可归纳如下:
非常欢迎对此行为的任何解释。
答案 0 :(得分:1)
这似乎是LINQ提供程序处理FirstOrDefault
的方式中的错误或不匹配 - 在我看来,它似乎为查询添加了一个LIMIT 1
,这显然不适用于急切加载(产生OUTER JOIN
)。
我通过显式转换为中间的可枚举来解决它:
var job = jobsRepo.Get()
.FetchMany(x => x.GroupRecipients)
.AsEnumerable()
.FirstOrDefault(j => j.Id == jobKey.Id);
这有点像黑客,但解决了这个问题。
可能,你的第二个例子是有效的,因为第一个例子将实体加载到缓存中,因此nHibernate不需要去数据库(并且遇到LINQ提供程序中的错误逻辑)。