如何在NHibernate 2.1.2中急切加载映射到非主键的子集合?

时间:2010-05-27 19:09:30

标签: nhibernate nhibernate-mapping mapping

我有两个对象,它们之间有多对多的关系,如下所示:

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; }
}

我正在使用遗留数据库,所以我的映射看起来像: 请注意,LeftHandSideRightHandSideRightHandSide的主键不在一列。

<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>

当我对LeftHandSide进行查询并急切加载该集合时出现问题:

LeftHandSide lhs =
    _session.CreateCriteria<LeftHandSide>()
            .Add(Expression.IdEq(13))
            .UniqueResult<LeftHandSide>();

工作得很好。但

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>();

抛出异常(见下文)。有趣的是,

RightHandSide rhs =
    _session.CreateCriteria<RightHandSide>()
            .Add(Expression.IdEq(127))
            .SetFetchMode("Lefts", FetchMode.Join) // <-- eager-load the other direction
            .UniqueResult<RightHandSide>();

似乎也很完美。

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)

我正在使用NHibernate 2.1.2并且我一直在调试NHibernate源代码,但我是空的。有什么建议?非常感谢!

0 个答案:

没有答案