2010-06-04 5 views
2

J'ai deux tables de base de données qui ont une relation plusieurs à plusieurs: personnes et organisation. Et bien sûr, il y a une table qui relie ces deux appelés OrganizationPeople. Dans le mappage NHibernate, ils ont chacun un Bag de l'autre. Dans la cartographie populaire, le sac est mis en correspondance comme celui-ci:Comment faire pour interroger plusieurs à plusieurs objets dans NHibernate

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

et la cartographie de l'Organisation le sac est comme

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

Ce que je suis en train de faire est maintenant interroger l'Organisation par OrgID pour trouver toutes les Les gens assocated utilisant 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>(); 


     } 

C'est ce que mon test unitaire retourné:

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 [email protected];@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 

Il semble qu'il a généré la requête corrigée en fonction du mappage, mais quelque chose est arrivé plus tard lors de la création du résultat de retour. Mais je ne suis pas sûr de ce qui cause cela.

Toute aide est grandement appréciée.

John

Répondre

2

Essayez ceci:

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

OUI! C'est ce que j'ai fait! Merci beaucoup. Par ailleurs, après que je posté ma question, j'ai essayé ce retour NHibernateSession.CreateCriteria (typeof (Organisation)) .Add (Restrictions.Eq ("OrgID", OrgID)) .CreateAlias ​​("Personnes "," p ", JoinType.InnerJoin) .List (); Cela fonctionne et le sql qu'il génère est identique à celui généré par votre solution. – John

+0

@John: vous pourriez toujours avoir besoin du 'DistinctRootEntityResultTransformer' –

+0

Mauricio, mon test d'unité ne s'est pas plaint sans elle. Je pense que le DistinctRootEntityResultTransformer peut ne pas être nécessaire ici parce que cette requête utilise l'API ICriteria au lieu de la HQL. C'était juste ma conjecture. – John

0

Je pense que si vous supprimez la jointure, la collection d'objets de gens associés seront paresseux chargés lorsque vous les accès. Si vous souhaitez que la collection soit chargée dans la même requête, cela devrait fonctionner:

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

Husain, merci pour l'entrée. J'ai essayé et ça a marché. Mais je ne vois pas de différence entre le SQL généré avec ou sans "fetch". Ai-je manqué quelque chose? – John

Questions connexes