2010-12-01 2 views
0

Frage: Wie man ein eifrig geladenes Kriterium erhält, um seitenweise Ergebnisse für die root-Entität mit allen untergeordneten Auflistungen zurückzugeben set fetchmode = eager.NHibernate Paging-Kriterien mit fetchmode eifrig. (unter Verwendung von fließendem NH)

Ich versuche, eine 10 Artikel ausgeleierte Ergebnismenge mit eifrig geladenen Kind Sammlungen zu bekommen. Das Problem ist, dass die Abfrage eine ausgewählte Top 10 um die gesamte Auswahl gewickelt hat. Das bewirkt, dass nur die ersten 10 Ergebnisse einschließlich aller verknüpften Datensätze zurückgegeben werden. Wenn die erste Entität 10 untergeordnete Objekte hat, gibt meine Ergebnismenge 1 Entität mit 10 untergeordneten Objekten zurück. Ich brauche die Entitäten und Kindersammlungen, die hydratisiert (faul) zurückgegeben werden. Wenn ich das lazy loading ausschalte und diese Abfrage ausführe, erhalte ich die n + 1-Abfrage für jeden Partner in der Ergebnismenge.

Das ist mein Grund Abfrage-Prozess:

criteria = context.Session.CreateCriteria<Associate>(); 
criteria.SetMaxResults(10); //hardcoded for testing 
criteria.SetFirstResult(1); //hardcoded for testing 
criteria.SetFetchMode("Roles", NHibernate.FetchMode.Eager); 
criteria.SetFetchMode("Messages", NHibernate.FetchMode.Eager); 
criteria.SetFetchMode("DirectReports", NHibernate.FetchMode.Eager); 
criteria.SetResultTransformer(new DistinctRootEntityResultTransformer()); 
return criteria.List<Associate>(); 


public AssociateMap() 
    { 
     ReadOnly(); 
     Id(x => x.AssociateId); 
     Map(x => x.FirstName); 
     Map(x => x.LastName); 
     Map(x => x.ManagerId); 
     Map(x => x.Department); 
     Map(x => x.Email); 
     Map(x => x.JobTitle); 

     Map(x => x.LastFirstName).Formula("LTRIM(RTRIM(LastName)) + ', ' + LTRIM(RTRIM(FirstName))"); 

     HasMany(x => x.Messages).KeyColumn("AssociateId").Inverse().Cascade.All(); 
     HasMany(x => x.Roles).Element("RoleKey"); 
     HasMany(x => x.DirectReports).KeyColumn("ManagerId").Cascade.None().ForeignKeyConstraintName("FK_Associate_Manager"); 
     //HasMany(x => x.DirectReports).Element("ManagerId").CollectionType(typeof(Domain.Associate)); 


    } 

Antwort

3

Die Lösung endete eine Unterabfrage mit dem max Ergebnisse einstellen. Ich habe die Unterabfrage mit Subqueries.PropertyIn hinzugefügt. Ich klemme die "Kriterien" auf "Begrenzer", weil ich den Kriteriumsausdruck im nicht gezeigten Code hinzugefügt habe. Also muss ich dieses Kriterium in die Unterabfrage klonen, damit die Top-10-Auswahl in der "IN" -Anweisung steht. Jetzt kann ich eifrig die Kindsammlungen laden und der Wurzeldentität Paginierung hinzufügen, um 10 enties ohne Probleme mit kartesischen oder n + 1 zu erhalten. Ich werde versuchen, einen umfassenderen und besser organisierten Code zu erstellen.

//criteria = context.Session.CreateCriteria<Associate>(); 
//changed criteria to DetachedCriteria. 
criteria = DetachedCriteria.For<Associate>(); 

DetachedCriteria limiter = CriteriaTransformer.Clone(criteria); 
limiter.SetProjection(Projections.Id()); 
limiter.SetMaxResults(10); 
criteria.Add(Subqueries.PropertyIn("AssociateId", limiter)); 

criteria.SetFetchMode("Roles", NHibernate.FetchMode.Eager); 
criteria.SetFetchMode("Messages", NHibernate.FetchMode.Eager); 
criteria.SetFetchMode("DirectReports", NHibernate.FetchMode.Eager); 
criteria.SetResultTransformer(new DistinctRootEntityResultTransformer()); 
return criteria.List<Associate>(); 
+0

Ich mag diese Lösung. –

+0

+1 für die Freigabe der Antwort. – kerzek