Hi,
I have two objects with a many-to-many relationship between them, as follows:
public class LeftHandSide
{
public LeftHandSide()
{
Name = String.Empty;
Rights = new HashSet<RightHandSide>();
}
public int Id { get; set; }
public string Name { get; set; }
public ICollection<RightHandSide> Rights { get; set; }
}
public class RightHandSide
{
public RightHandSide()
{
OtherProp = String.Empty;
Lefts = new HashSet<LeftHandSide>();
}
public int Id { get; set; }
public string OtherProp { get; set; }
public ICollection<LeftHandSide> Lefts { get; set; }
}
and I'm using a legacy database, so my mappings look like:
Notice that LeftHandSide
and RightHandSide
are associated by a different column than RightHandSide
's primary key.
<class name="LeftHandSide" table="[dbo].[lefts]" lazy="false">
<id name="Id" column="ID" unsaved-value="0">
<generator class="identity" />
</id>
<property name="Name" not-null="true" />
<set name="Rights" table="[dbo].[lefts2rights]">
<key column="leftId" />
<!-- THIS IS THE IMPORTANT BIT: I MUST USE PROPERTY-REF -->
<many-to-many class="RightHandSide" column="rightProp" property-ref="OtherProp" />
</set>
</class>
<class name="RightHandSide" table="[dbo].[rights]" lazy="false">
<id name="Id" column="id" unsaved-value="0">
<generator class="identity" />
</id>
<property name="OtherProp" column="otherProp" />
<set name="Lefts" table="[dbo].[lefts2rights]">
<!-- THIS IS THE IMPORTANT BIT: I MUST USE PROPERTY-REF -->
<key column="rightProp" property-ref="OtherProp" />
<many-to-many class="LeftHandSide" column="leftId" />
</set>
</class>
The problem comes when I do a query for LeftHandSide
's and eager-load the collection:
LeftHandSide lhs =
_session.CreateCriteria<LeftHandSide>()
.Add(Expression.IdEq(13))
.UniqueResult<LeftHandSide>();
works just fine. But
LeftHandSide lhs =
_session.CreateCriteria<LeftHandSide>()
.Add(Expression.IdEq(13))
.SetFetchMode("Rights", FetchMode.Join) // <-- I really do want to eager-load this collection in this one particular usage scenario.
.UniqueResult<LeftHandSide>();
throws an exception (see below). Interestingly,
RightHandSide rhs =
_session.CreateCriteria<RightHandSide>()
.Add(Expression.IdEq(127))
.SetFetchMode("Lefts", FetchMode.Join) // <-- eager-load the other direction
.UniqueResult<RightHandSide>();
seems to be perfectly fine as well.
NHibernate.Exceptions.GenericADOException Message: Error performing LoadByUniqueKey[SQL: SQL not available] Source: NHibernate StackTrace: c:\opt\nhibernate\2.1.2\source\src\NHibernate\Type\EntityType.cs(563,0): at NHibernate.Type.EntityType.LoadByUniqueKey(String entityName, String uniqueKeyPropertyName, Object key, ISessionImplementor session) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Type\EntityType.cs(428,0): at NHibernate.Type.EntityType.ResolveIdentifier(Object value, ISessionImplementor session, Object owner) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Type\EntityType.cs(300,0): at NHibernate.Type.EntityType.NullSafeGet(IDataReader rs, String[] names, ISessionImplementor session, Object owner) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Persister\Collection\AbstractCollectionPersister.cs(695,0): at NHibernate.Persister.Collection.AbstractCollectionPersister.ReadElement(IDataReader rs, Object owner, String[] aliases, ISessionImplementor session) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Collection\Generic\PersistentGenericSet.cs(54,0): at NHibernate.Collection.Generic.PersistentGenericSet`1.ReadFrom(IDataReader rs, ICollectionPersister role, ICollectionAliases descriptor, Object owner) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Loader\Loader.cs(706,0): at NHibernate.Loader.Loader.ReadCollectionElement(Object optionalOwner, Object optionalKey, ICollectionPersister persister, ICollectionAliases descriptor, IDataReader rs, ISessionImplementor session) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Loader\Loader.cs(385,0): at NHibernate.Loader.Loader.ReadCollectionElements(Object[] row, IDataReader resultSet, ISessionImplementor session) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Loader\Loader.cs(326,0): at NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Loader\Loader.cs(453,0): at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Loader\Loader.cs(236,0): at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Loader\Loader.cs(1649,0): at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Loader\Loader.cs(1568,0): at NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Loader\Loader.cs(1562,0): at NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces, IType[] resultTypes) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Loader\Criteria\CriteriaLoader.cs(73,0): at NHibernate.Loader.Criteria.CriteriaLoader.List(ISessionImplementor session) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Impl\SessionImpl.cs(1936,0): at NHibernate.Impl.SessionImpl.List(CriteriaImpl criteria, IList results) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Impl\CriteriaImpl.cs(246,0): at NHibernate.Impl.CriteriaImpl.List(IList results) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Impl\CriteriaImpl.cs(237,0): at NHibernate.Impl.CriteriaImpl.List() c:\opt\nhibernate\2.1.2\source\src\NHibernate\Impl\CriteriaImpl.cs(398,0): at NHibernate.Impl.CriteriaImpl.UniqueResult() c:\opt\nhibernate\2.1.2\source\src\NHibernate\Impl\CriteriaImpl.cs(263,0): at NHibernate.Impl.CriteriaImpl.UniqueResult[T]() D:\proj\CMS3\branches\nh_auth\DomainModel2Tests\Authorization\TempTests.cs(46,0): at CMS.DomainModel.Authorization.TempTests.Test1() Inner Exception System.Collections.Generic.KeyNotFoundException Message: The given key was not present in the dictionary. Source: mscorlib StackTrace: at System.ThrowHelper.ThrowKeyNotFoundException() at System.Collections.Generic.Dictionary`2.get_Item(TKey key) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs(2047,0): at NHibernate.Persister.Entity.AbstractEntityPersister.GetAppropriateUniqueKeyLoader(String propertyName, IDictionary`2 enabledFilters) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs(2037,0): at NHibernate.Persister.Entity.AbstractEntityPersister.LoadByUniqueKey(String propertyName, Object uniqueKey, ISessionImplementor session) c:\opt\nhibernate\2.1.2\source\src\NHibernate\Type\EntityType.cs(552,0): at NHibernate.Type.EntityType.LoadByUniqueKey(String entityName, String uniqueKeyPropertyName, Object key, ISessionImplementor session)
I'm using NHibernate 2.1.2 and I've been debugging into the NHibernate source, but I'm coming up empty. Any suggestions? Thanks so much!