2010-02-19 3 views
8

i ont une classe parent qui a deux collections enfants ChildCollectionA et ChildCollectionB. ChildCollectionA est cartographié comme une association, et a son propre ID:Nhibernate: chargement désireux deux collections enfants (l'un étant une liste des composants)

HasMany(parent => parent.ChildCollectionA) 
.KeyColumn("IDParent") 
.AsBag().Cascade.AllDeleteOrphan(); 

et ChildCollectionB est mis en correspondance a une liste des composants:

HasMany(parent => parent.ChildCollectionB) 
    .Table("ChildCollectionBTable") 
    .KeyColumn("IDParent") 
    .Component(m=> 
       { 
        m.References(childB => childB.Task, "IDTask").Not.LazyLoad().Not.Nullable(); 
        m.Map(childB => childB.Date, "Date").Not.Nullable(); 

       } 
     ) 
    .AsBag().Cascade.AllDeleteOrphan(); 

J'ai besoin maintenant tous les parents dans la base, parce que je doivent effectuer certaines opérations qui ont besoin à la fois ChildCollectionA et ChildCollectionB.

donc je devais à la charge désireux eux, j'utilisé mode de récupération à la charge ChildCollectionA désireux d'abord:

var = queryParents session.createCriteria() .SetFetchMode ("ChildCollectionA", FetchMode.Eager) (• Ajoutez Expression.Le ("ParentDate", endDate));

Il est revenu 492 parents (devrait être 481), la valeur totale de l'opération i était 32,847.46 € effectué (devrait être 30,790.87 €). Donc, je doit éliminer les doublons parents:

var queryParents = session.CreateCriteria<Parent>() 
    .SetFetchMode("ChildCollectionA", FetchMode.Eager) 
    .Add(Expression.Le("ParentDate",endDate)) 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()); 

J'ai essayé la même charge désireux avec juste le ChildCollectionB

var queryParents = session.CreateCriteria<Parent>() 
    .SetFetchMode("ChildCollectionB", FetchMode.Eager) 
    .Add(Expression.Le("ParentDate",endDate)) 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()); 

Dans les deux cas retourné 481 les parents OK, et la valeur était 30,790.87 € OK.

Mais je devais charge désireux deux collections en même temps, je l'ai fait:

var queryParents = session.CreateCriteria<Parent>() 
    .SetFetchMode("ChildCollectionA", FetchMode.Eager) 
    .SetFetchMode("ChildCollectionB", FetchMode.Eager) 
    .Add(Expression.Le("ParentDate",endDate)) 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()); 

Il est revenu 481 parents, OK, et la valeur était 32,602.57 € (devrait être 30,790.87 €).

Maintenant, le nombre de parents retournés est correct, mais il existe des doublons ailleurs, les valeurs dépendent des collections et non du parent, donc les doublons doivent se trouver quelque part dans ChildCollections.

En ce moment je suis en utilisant une solution laide:

var queryParents = session.CreateCriteria<Parent>() 
    .SetFetchMode("ChildCollectionA", FetchMode.Eager) 
    .Add(Expression.Le("ParentDate",endDate)) 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()); 

parents= queryParents.List<Parent>(); 

    foreach (Parent p in parents) 
    { 
     NHibernateUtil.Initialize(p.ChildCollectionB); 
    } 

Il est revenu 481 parents, OK, et la valeur était 30,790.87 € OK.

Le problème se produit lorsque je charge les deux collections avec impatience, si je veux en charger un seul, puis que je force le chargement à l'autre, cela fonctionne. Je ne sais pas si le mappage de ChildCollectionB étant une liste de composants au lieu d'une association a quelque chose à voir avec cela ...

Des indices?

Merci

Répondre

4

je crois que le problème est le produit cartésien entre les deux collections ne sont pas traitées par le DistinctRootEntityTransformer ... de sorte que vous aurez des données dupliquées dans les collections quelque part.

Pour charger plusieurs collections avec enthousiasme que ça va prendre plusieurs requêtes.

var queryParents = session.CreateCriteria<Parent>() 
    .SetFetchMode("ChildCollectionA", FetchMode.Eager) 
    .Add(Expression.Le("ParentDate",endDate)) 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()); 

//load CollectionB in second query...it's linked together by NH 
session.CreateCriteria<Parent>() 
    .SetFetchMode("ChildCollectionB", FetchMode.Eager) 
    .Add(Expression.Le("ParentDate",endDate)) 
    .List(); 

Ce que je fais normalement est de récupérer l'entité principale avec toutes les associations plusieurs-à-un requises. Ensuite, je vais chercher avec impatience les collections requises dans la session avec un MultiCriteria. Si ce n'est que deux collections, j'aime faire un peu plus haut et aller chercher la première collection avec des caractères distinctifs.

Pour plus d'informations voir Eager loading aggregate with many child collections

+0

Toute idée si cela a été essayé avec la version 4 NHibernate spécifiquement 4.0.4? Il semble que cette solution ne fonctionne pas dans cette version. –

Questions connexes