我有一个我想要加载的对象,我想急切地加载几个父元素,还有一些祖父元素。我已经设置了我的选择:
var events = (from ed in eventRepo._session.Query<EventData>() where idsAsList.Contains(ed.Id) select ed)
.FetchMany(ed => ed.Parents)
.ThenFetchMany(pa => pa.Grandparents)
.ThenFetch(gp => gp.GreatGrandparents)
// other fetches here for other attributes
.ToList();
我的问题是,如果我只是.FetchMany
父母,我会得到正确数量的元素。一旦我加上祖父母,我就会变得太多,而且对于曾经的祖父母来说,这种情况会变得更多。
它显然正在做某种笛卡尔产品,所以我环顾四周,发现有些人使用变形金刚来解决这个问题。我看了一下并尝试实现它,但添加.TransformUsing()
会导致编译器错误,因为我似乎无法在此类调用上调用.TransformUsing()
。
从这样的调用中获取正确数量的元素的正确方法是什么,由于计算笛卡尔积而没有重复?
答案 0 :(得分:0)
这是一个非常受欢迎的帖子,它使用Futures来做这种类型的负载以避免笛卡尔产品。它不像在单个查询中那样优雅,但它可以完成工作。
Fighting cartesian product (x-join) when using NHibernate 3.0.0
另一种可能的解决方案是将您的集合定义为集合而不是行李。这也可以避免笛卡尔产品问题。我不太喜欢这个解决方案,因为你必须使用nhibernate特定的集合类型,但它已知可以工作。
答案 1 :(得分:0)
如果明确强制NHibernate连接,那么你可以做的事情就不多了。数据库将多次返回相同的实体(这是完全正常的,因为您的查询进行了笛卡尔连接)。如果您多次询问同一项目,NHibernate无法区分。 NHibernate不知道你的意图。但有一个解决方法。您可以添加以下行
var eventsSet = new HashSet<Events>(events);
假设您的实体覆盖了Equals和GetHashCode,您将获得唯一的事件。