views:

201

answers:

0

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!

related questions