2010-11-26 2 views
2

Je veux renvoyer un objet parent avec la collection enfants très chargée avec la page demandée (sous-ensemble) d'objets enfants. Quel est le meilleur moyen d'y parvenir? Filtres? Est-ce possible avec une requête ICriteria? J'utilise .SetFirstResult() et .SetMaxResults() pour faire la pagination pour les collections de résultats racines agrégées, mais est-il possible d'utiliser cela avec l'agrégat root pour sélectionner la page des résultats enfants?NHibernate: moyen le plus simple de renvoyer un objet avec une collection d'enfants paginés?

Quelque chose le long de ces lignes:

public class Parent{ 
int Id; 
IList<Child> Children; 
} 


public Parent GetWithPagedChildren(int id, int page, int pageSize, out int count) 
{ 
    //Query 

    return Parentresult; //With one page of children populated. 
} 

MISE À JOUR:

En fait, l'exigence de chargement avec impatience est pas si important. Je veux juste que le sous-ensemble paginé des objets enfants soit chargé quand j'y accède.

+0

Pourquoi voulez-vous paginer les enfants? Sont-ils trop nombreux pour entrer dans la mémoire? –

+0

@Stefan: Il semble juste incorrect et inutile de récupérer la totalité de la collection enfant de la base de données quand je sais que seul un petit sous-ensemble est nécessaire. – UpTheCreek

Répondre

4

Vous ne pouvez pas vous joindre à la page-fetch collections enfants dans la même requête. Mais vous pouvez:

Mise à jour (pour les nouvelles exigences):

Comme vous l'avez lu, vous pouvez utiliser session.CreateFilter pour filtrer/trier/page un collection enfant . Cela fonctionne et il est supporté partout.

De plus, il y a un correctif (NH-2319, je vais convertir en addin, car il est peu probable qu'il soit accepté dans le coffre) qui permet d'utiliser Linq pour cela. Il est limité à certains types de collecte et exige que la relation soit bidirectionnelle, mais permet:

var parent = GetParent(); 
var secondPageOfChildrenByName = parent.Children.AsQueryable() 
               .OrderBy(c => c.Name) 
               .Skip(PageSize * 1) 
               .Take(PageSize) 
               .ToList(); 
+0

C'est dommage, cela doit être un scénario très commun. Surtout quand on s'en tient aux règles DDD et qu'on accède uniquement aux objets via la traversée racine agrégée (je peux construire un dépôt enfant, mais cela signifie un référentiel pour chaque entité, plutôt que seulement les racines agrégées.) Le premier exemple ne va pas aider. Je pense. La deuxième option est-elle seulement disponible en v3? J'utilise v2.2. malheureusement. – UpTheCreek

+0

La deuxième option est disponible en 2.x, c'est ce que j'utilise en ce moment, et est compatible avec DDD. –

+0

Ok merci. J'ai lu ce (un peu vieux) post par ayende sur ceci (http://ayende.com/Blog/2006/09/16/BatchingSupportInNHibernate.aspx) - il déclare que ceci est seulement soutenu pour MSSQL. Savez-vous si cela a changé? – UpTheCreek

1

Il suffit de lire ce bit dans le NHibernate Documentation 'Querying tips and tricks' section (13.13):

//Collections are pageable by using the IQuery interface with a filter: 

IQuery q = s.CreateFilter(collection, ""); // the trivial filter 
q.setMaxResults(PageSize); 
q.setFirstResult(PageSize * pageNumber); 
IList page = q.List(); 

Je ne suis pas tout à fait sûr encore comment cela fonctionnera avec une collection enfant mais l'essaiera et mettra à jour cette réponse.

Questions connexes