Reputation: 32401
When doing a query like this (using Nhibernate 2.1.2):
ICriteria criteria = session.CreateCriteria<MyRootType>()
.SetFetchMode("ChildCollection1", FetchMode.Eager)
.SetFetchMode("ChildCollection2", FetchMode.Eager)
.Add(Restrictions.IdEq(id));
I am getting multiple duplicate objects in some cartesian fashion. E.g. if ChildCollection1
has 3 elements, and ChildColection2
has 2 elements then I get results with each element in ChildColection1
one duplicated, and each element in ChildColection2
triplicated! This was a bit of a WTF moment for me...
So how to do this correctly?
Update:
As per Felice's suggestion, I tried using the DistinctRootEntity transformer, but this is still returning duplicates. Code:
ICriteria criteria = session.CreateCriteria<MyRootType>()
.SetFetchMode("ChildCollection1", FetchMode.Eager)
.SetFetchMode("ChildCollection2", FetchMode.Eager)
.Add(Restrictions.IdEq(id));
criteria.SetResultTransformer(Transformers.DistinctRootEntity);
return criteria.UniqueResult<MyRootType>();
Upvotes: 16
Views: 5726
Reputation: 17869
Try using Futures:
ICriteria criteriaFuture1
= session.CreateCriteria<MyRootType>()
.SetFetchMode("ChildCollection1", FetchMode.Eager)
.Add(Restrictions.IdEq(id))
.SetResultTransformer(Transformers.DistinctRootEntity)
.FutureValue<MyRootType>();
ICriteria criteriaFuture2
= session.CreateCriteria<MyRootType>()
.SetFetchMode("ChildCollection2", FetchMode.Eager)
.Add(Restrictions.IdEq(id))
.SetResultTransformer(Transformers.DistinctRootEntity)
.FutureValue<MyRootType>();
return criteriaFuture1.Value;
Upvotes: 2
Reputation: 67128
What were you mapping your collection as? If your using a bag for example you will get duplicates. You can use a set instead and you won't get duplicates.
Upvotes: 3
Reputation: 19478
I am not using NHibernate (rather, regular 'ol Hibernate), but in the Java version of Hibernate you can define One-To-Many collections as either Lists or Sets. If you define them as Sets you will not get duplicates. Surprisingly enough, this happens without overriding equals(). Unfortunately, I have the same problem and I want Lists so I can integrate with Wicket but no duplicates...
Upvotes: 3
Reputation: 99750
You're doing a cartesian product here. Don't. Instead, fetch each collection separately.
BTW: this isn't something NHibernate-specific, the same applies to any ORM in any platform, or even pure SQL without any ORM at all. In general, you don't want to fetch N*M rows when you can fetch N+M instead.
Upvotes: 11
Reputation: 33272
You can select single distinct results by specifying SetResultsTransformer(Transformers.DistinctRootEntity);
Upvotes: 15