2013-10-09 9 views
5

Ich versuche, eine Einheit zu wählen und holen eine ähnliche Liste resultierende:NHibernate QueryOver mit Fetch mehrere SQL-Abfragen und db trifft

Session.QueryOver<UserRole>() 
      .Fetch(x => x.UsersInRole).Eager 
      .List(); 

was eine Menge von Datenbank-Hits. Die erste ist so etwas wie:

SELECT ... FROM UserRoles 
left outer join UsersInRoles on ... 

und Hunderte weitere separate Abfragen, die so etwas wie folgt aussieht:

SELECT ... FROM UsersInRoles 
left outer join UserRoles on ... 
WHERE UserRoles.UserId=? 

Die Abbildung ist, wie folgend:

public class UserRoleMap : ClassMap<UserRole> 
{ 
    public UserRoleMap() 
    { 
     Id(x => x.Id); 
     Map(x => x.RoleName); 
     HasManyToMany(x => x.UsersInRole) 
     .Inverse() 
     .LazyLoad() 
     .Table("UsersInRoles"); 
    } 
} 

Antwort

3

Ich würde sagen, dass dieses Verhalten ist, was wir erwarten sollten. Lassen Sie uns ein Szenario haben, in denen wir im System haben 2 Benutzer und 2 Rollen

User1 - Role1 // has only Role1 
User2 - Role1 // now we see that Role2 has more then User1 
User2 - Role2 

Lassen Sie uns sagen, dass die erste Abfrage, abruft nur User1 und seine many-to-many-Beziehung Role1. Was wir in der ISession im Moment haben, ist nur User1, so die Menge der Nutzer, Role1 ist unvollständig(wir können keine Objekte wiederverwenden geladen ISession im Moment). Aber wie soll man wissen, wo wir sind? Dass alle geladenen Daten für Role1 in der Sitzung sind oder nicht?

Neue Abfrage, Laden der Daten für Role1 muss ausgegeben werden. Und auf diese Weise können wir am Ende haben dosen dieser Abfragen ...

Was ich als die beste Lösung zu sehen (ich bin mit in fast alle Szenarien) ist die batch-size Einstellung: 19.1.5. Using batch fetching

HasManyToMany(x => x.UsersInRole) 
    ... 
    .BatchSize(25) 

Markieren Sie alle Ihre Sammlung Karten mit .BatchSize(25) und tun dies auch für die Class-Map. Das wird mehr als 1 SQL Script verursachen, aber am Ende nicht mehr als 1 + (2-4) abhängig von der Batch-Größe und Seitengröße.

+0

Versuchte Ihren Vorschlag. Hat sich in 1 + 12 Abfragen ergeben - VIEL besser als vorher, aber gibt es nicht einen Weg, um weniger als 12 zu machen? (Erhöhung der Batch-Größe?) - Was kostet die Batch-Größe? Ich würde sagen, wenn es alles gut wäre, wäre es standardmäßig eingestellt worden. Ist die Losgröße die einzige Lösung? Gibt es nicht einen möglichen Join, der zu 2 Abfragen führt? Wenn ich es nötig hätte, es mir selbst mit simpler SQL zu schreiben, wären 2 Anfragen ausreichend gewesen. Vielen Dank. –

+1

Wenn es eine bessere Lösung als Losgröße gibt, bin ich mir vielleicht nicht sicher. Der Grund, warum dies nicht standardmäßig aktiviert ist, könnte die Tatsache sein, dass dies die einfache Logik sprengt: Das Proxy-Objekt für das Nicht-Initialisieren ist ein Treiber. Bei Bedarf greift es direkt auf seine Daten zu. Die Batch-Sizing verschiebt den Aufwand für die Sitzung, um diese SELECTS zu verbinden. Wie auch immer, Batch-Größe bezieht sich auf alle * unsere * Sammlungen und Klassenzuordnungen. Und die Leistung ist selbst bei großen Sets erstaunlich –