After upgrading to NHibernate 4.0, the following code started to fail:
var result = session.QueryOver<Employee>() | |
.JoinAlias(e => e.Orders, () => orderAlias, JoinType.LeftOuterJoin) | |
.JoinAlias(e => orderAlias.OrderDetails, () => orderDetailAlias, JoinType.LeftOuterJoin) | |
.List<Employee>(); |
Before I could easily fetch a collection together with its children and grand-children, but now I got the following error message instead:
NHibernate.QueryException : Cannot simultaneously fetch multiple bags.
StackTrace:
at NHibernate.Loader.BasicLoader.PostInstantiate() in n:\nhibernate-core\src\NHibernate\Loader\BasicLoader.cs:line 38
at NHibernate.Impl.SessionImpl.List(CriteriaImpl criteria, IList results) in n:\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs:line 1880
at NHibernate.Impl.CriteriaImpl.List(IList results) in n:\nhibernate-core\src\NHibernate\Impl\CriteriaImpl.cs:line 265
at NHibernate.Impl.CriteriaImpl.List[T]() in n:\nhibernate-core\src\NHibernate\Impl\CriteriaImpl.cs:line 277
at Test.Data.Tests.MultipleChildCollectionsTests.Fetch_GrandChildren_Using_QueryOver_And_JoinAlias_Statement() in c:\Projects\Tests\MultipleChildCollectionsTests.cs:line 83
Here was the class I used:
public class Employee | |
{ | |
public virtual int EmployeeID { get; set; } | |
//Removed some irrelevant properties | |
public virtual ICollection<Order> Orders { get; set; } | |
} |
And here is the corresponding mapping file:
<hibernate-mapping default-cascade="none" xmlns="urn:nhibernate-mapping-2.2"> | |
<class name="Test.Data.Domain.Employee, Test.Data" table="Employees"> | |
<id name="EmployeeID" type="System.Int32" column="EmployeeID" unsaved-value="0"> | |
<generator class="native" /> | |
</id> | |
<bag name="Orders" inverse="false" lazy="true" cascade="none"> | |
<key> | |
<column name="EmployeeID" not-null="false" /> | |
</key> | |
<one-to-many class="Test.Data.Domain.Order, Test.Data" /> | |
</bag> | |
</class> | |
</hibernate-mapping> |
Important to notice in the code above is that I’m still using the ICollection interface together with a bag in the XML mapping. The reason I was using a bag is because this is old code and there was no ISet interface built into older versions of .NET. In .NET 4.0 an ISet interface was introduced, so there is no reason to use a bag anymore.
Let’s update the code:
public class Employee | |
{ | |
public virtual int EmployeeID { get; set; } | |
public virtual ISet<Order> Orders { get; set; } | |
} |
<hibernate-mapping default-cascade="none" xmlns="urn:nhibernate-mapping-2.2"> | |
<class name="Test.Data.Domain.Employee, Test.Data" table="Employees"> | |
<id name="EmployeeID" type="System.Int32" column="EmployeeID" unsaved-value="0"> | |
<generator class="native" /> | |
</id> | |
<set name="Orders" inverse="false" lazy="true" cascade="none"> | |
<key> | |
<column name="EmployeeID" not-null="false" /> | |
</key> | |
<one-to-many class="Test.Data.Domain.Order, Test.Data" /> | |
</set> | |
</class> | |
</hibernate-mapping> |
After switching to a set, the error went away. Double win!