2012-05-29 7 views
7

ich eine Liste aller verschiedenen Kontonamen Präfixe haben (az), die ichGroupBy SqlFunction auf QueryOver

var accounts = this.SessionManager.GetActiveSession().QueryOver<Account>(); 

var q = accounts.Select(Projections.Distinct(
     Projections.SqlFunction("substring", 
           NHibernateUtil.String, 
           Projections.Property("Name"), 
           Projections.Constant(1), 
           Projections.Constant(1)))); 

jedoch erwerben mit, was ich will zu tun ist, anstatt eine eigene Liste der zurückkehr Gruppe die Präfixe und Rückkehr Die Anzahl der Konten, die mit diesem Präfix beginnen, aber ich bin nicht sicher, wie eine Gruppe mithilfe von Query ausgeführt wird, da sie nicht so einfach ist wie die Standard-Linkliste.

Der Grund, warum ich QueryOver und nicht Query verwende, liegt daran, dass die Teilstring-Funktion aus irgendeinem Grund im Speicher und nicht auf dem Datenbankserver ausgeführt wird.

Dies ist, wie ich in der Regel würde es tun

var prefixes = (from acc in this.SessionManager.GetActiveSession().Query<Account>() 
       group acc by acc.Name.Substring(0, 1) 
       into grp 
       select new 
         { 
         Prefix = grp.Key, 
         Count = grp.Count() 
         }); 

bearbeiten Dies ist, was ich versuchte, aber ich erhielt den folgenden Fehler

Unerkannte Methodenaufruf in Ausdruck SqlFunction ("Teilzeichenfolge “NHibernateUtil.String, new [] {Eigenschaft ("Name"), Constant (Rechnen (1)), Constant (Rechnen (1))})

var accounts = this.SessionManager.GetActiveSession().QueryOver<Account>().Select(
      Projections.Group<string>(x => Projections.SqlFunction("substring", NHibernateUtil.String, 
                 Projections.Property("Name"), Projections.Constant(1), 
                 Projections.Constant(1))), 
      Projections.Count<string>(x => Projections.SqlFunction("substring", NHibernateUtil.String, 
                 Projections.Property("Name"), Projections.Constant(1), 
                 Projections.Constant(1))) 

     ); 

Antwort

4

Sie können es Projections.SqlGroupProjection tun zu verwenden, wenn alles andere fehlschlägt!

var accounts = _busDb.Session.QueryOver<QueueEntity>() 
     .Select(
      Projections.SqlGroupProjection(
       "SUBSTRING({alias}.Name, 1) as FirstChar", 
       "SUBSTRING({alias}.Name, 1)", 
       new[] {"FirstChar"}, 
       new[] {NHibernateUtil.String}), 
      Projections.Count("id")); 

Das erste Argument ist, was in der Auswahl ausgewählt wird, wird das zweite Argument, was durch gruppiert ist, das dritte Argument ist der Name der Spalte (n), die ausgewählt werden, und das vierte Argument ist der Typ der Daten, die ausgewählt werden.

+0

Die Teilstring-Funktion benötigt einen zusätzlichen Parameter, aber das hat das Problem gelöst. Vielen Dank – JConstantine

3

wie groß ist Ihre Liste? Wenn es weniger als 1000 würde ich Artikellisten sammeln von SQL Server dann Ihre regelmäßige Gruppe durch Abfrage der

Liste durchführen
var sqlout= (from acc in this.SessionManager.GetActiveSession().Query<Account>() 
      select new 
        { 
        Name = acc.Name, 
        col1= acc.col1 
        }).TolList(); 

und dann

var prefixes = (from acc in sqlout 
      group acc by acc.Name.Substring(0, 1) 
      into grp 
      select new 
        { 
        Prefix = grp.Key, 
        Count = grp.Count() 
        }); 

Substring würde hier seit seinem Laufe auf C# Funktion arbeiten Liste nicht auf sQL Server

+0

Im Moment betrachten wir Listen mit über 20k Konten. :( – JConstantine

3

Haben Sie darüber nachgedacht die Notwendigkeit für die Teilzeichen Abfrage Beseitigung der durch den ersten Buchstaben des Namens in einer separaten Spalte zu speichern?

Angenommen, Sie SQL Server verwenden, können Sie es eine persistente berechnete Spalte machen zu vermeiden, um den Code aktualisieren zu müssen, die Einsätze/aktualisiert die Tabelle.

Die Fähigkeit, einen Index enthält diese Spalte hinzuzufügen, sollten Sie auch Ihre Abfrageleistung zu verbessern.

+0

+1 Als eine langfristige Lösung wird dies wahrscheinlich die Art sein, wie wir dieses Problem angehen müssen. Wird es definitiv behalten Verstand – JConstantine