【问题标题】:How to Query Many to Many Objects in NHibernate如何在 NHibernate 中查询多对多对象
【发布时间】:2010-06-05 02:06:25
【问题描述】:

我有两个具有多对多关系的数据库表:人员和组织。当然,还有一张表将这两者联系起来,称为 OrganizationPeople。

在 NHibernate 映射中,它们每个都有一个 Bag 的另一个。在 People 的映射中,Bag 是这样映射的:

  <bag name="Organizations" table="OrganizationPeople" cascade="none" inverse="false" lazy="true">
      <key column="PersonId"/>
      <many-to-many column="OrgId" class="DataTransfer.Organization, DataTransfer" fetch="select"/>
    </bag>

Organization 对 Bag 的映射就像

  <bag name="Persons" table="OrganizationPeople" cascade="none" inverse="false" lazy="true">
      <key column="OrgId"/>
      <many-to-many column="PersonId" class="DataTransfer.People, DataTransfer" fetch="select"/>
    </bag>

我现在要做的是通过 OrgId 查询组织以找出所有使用此 HQL 的相关人员:

 public IList<Organization> GetByOrgIdAndUserId(System.Guid orgId)
        {
            return NHibernateSession.CreateQuery("from Organization o join o.Persons as p where o.OrgId = :orgId")
                .SetGuid("orgId", orgId)
                .List<Organization>();


        }

这是我的单元测试返回的:

NHibernate: select organizati0_.OrgId as OrgId21_0_, people2_.PersonId as PersonId12_1_, organizati0_.EmployerIdentificationNo as Employer2_21_0_, organizati0_.InactiveDate as Inactive3_21_0_, organizati0_.OrgName as OrgName21_0_, organizati0_.UDSId as UDSId21_0_, organizati0_.ExternalOrgTypeCode as External6_21_0_, organizati0_.OrgInstance as OrgInsta7_21_0_, organizati0_.DUNS as DUNS21_0_, organizati0_.ProfileFileNumber as ProfileF9_21_0_, organizati0_.CentralRegistryEntityIdentificationNo as Central10_21_0_, organizati0_.PMSOrganizationFlag as PMSOrga11_21_0_, organizati0_.PIN as PIN21_0_, organizati0_.CreatedDate as Created13_21_0_, organizati0_.LastUpdateDate as LastUpd14_21_0_, organizati0_.InstitutionCode as Institu15_21_0_, organizati0_.WebURL as WebURL21_0_, people2_.FirstName as FirstName12_1_, people2_.LastName as LastName12_1_, people2_.Title as Title12_1_, people2_.UserId as UserId12_1_, people2_.GenderCode as GenderCode12_1_, people2_.EmployeeTypeCode as Employee7_12_1_, people2_.EmployeeStatusCode as Employee8_12_1_, people2_.PreferredContactMethodCode as Preferre9_12_1_ from IKNSubmissions.dbo.ExternalOrganizations organizati0_ inner join IKNSubmissions.dbo.OrganizationPeople persons1_ on organizati0_.OrgId=persons1_.OrgId inner join IKNSubmissions.dbo.People people2_ on persons1_.PersonId=people2_.PersonId where organizati0_.OrgId=@p0;@p0 = b7a8fda8-a65a-4607-81ca-e374fe75d685

System.ArgumentException: The value "System.Object[]" is not of type "IKN.DataTransfer.Organization" and cannot be used in this generic collection.
Parameter name: value
at System.ThrowHelper.ThrowWrongValueTypeArgumentException(Object value, Type targetType)
at System.Collections.Generic.List`1.VerifyValueType(Object value)
at System.Collections.Generic.List`1.System.Collections.IList.Add(Object item)
at NHibernate.Util.ArrayHelper.AddAll(IList to, IList from)
at NHibernate.Engine.Query.HQLQueryPlan.PerformList(QueryParameters queryParameters, ISessionImplementor session, IList results)
at NHibernate.Impl.SessionImpl.List(String query, QueryParameters queryParameters, IList results) 
NHibernate.Exceptions.GenericADOException: Could not execute query[SQL: SQL not available]
at NHibernate.Impl.SessionImpl.List(String query, QueryParameters queryParameters, IList results)
at NHibernate.Impl.SessionImpl.List<T>(String query, QueryParameters parameters)
at NHibernate.Impl.QueryImpl.List<T>()
at IKN.DataAccess.OrganizationDao.GetByOrgIdAndUserId(Guid orgId) in OrganizationDao.cs: line 16
at IKNDataAccessTest.OrganizationTest.CanGetByOrgId() in OrganizationTest.cs: line 42 

它似乎生成了基于映射更正的查询,但后来在创建返回结果时发生了一些事情。但我不确定是什么原因造成的。

非常感谢任何帮助。

约翰

【问题讨论】:

    标签: nhibernate many-to-many


    【解决方案1】:

    试试这个:

     return NHibernateSession.CreateQuery("select o from Organization o join o.Persons as p where o.OrgId = :orgId")
       .SetGuid("orgId", orgId)
       .SetResultTransformer(new DistinctRootEntityResultTransformer())
       .List<Organization>();
    

    【讨论】:

    • 是的!做到了!太感谢了。顺便说一句,在我发布我的问题后,我尝试了这个 return NHibernateSession.CreateCriteria(typeof(Organization)) .Add(Restrictions.Eq("OrgId", orgId)) .CreateAlias("Persons", "p", JoinType. InnerJoin) .List();它可以工作,并且它生成的 sql 与您的解决方案生成的 sql 相同。
    • @John:你可能还需要DistinctRootEntityResultTransformer
    • Mauricio,没有它我的单元测试没有抱怨。我认为这里可能不需要 DistinctRootEntityResultTransformer 是因为此查询使用 ICriteria API 而不是 HQL。这只是我的猜测。
    【解决方案2】:

    我认为如果您删除联接,则关联的 People 对象的集合在您访问它们时将被延迟加载。如果您希望在同一个查询中加载集合,那么这应该可以:

    select o from Organization o join fetch o.Persons as p where o.OrgId = :orgId
    

    【讨论】:

    • 侯赛因,感谢您的意见。我试过了,它奏效了。但我没有看到生成的 SQL 有或没有“获取”之间的区别。我错过了什么吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-13
    • 1970-01-01
    相关资源
    最近更新 更多