2012-05-29 10 views
7

Tengo una lista de todos los nombres de cuenta de prefijos distintos (az), que adquiero usandoGroupBy SqlFunction en 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)))); 

Sin embargo lo que yo quiero hacer es en lugar de devolver una lista distinta es el grupo de los prefijos y vuelta la cantidad de cuentas que comienzan con ese prefijo, pero no estoy seguro de cómo realizar un grupo al usar query over ya que no es tan sencillo como el linq estándar.

La razón por la que estoy utilizando QueryOver y no Query es porque, por alguna razón, la función de subcadena se está realizando en la memoria y no en el servidor de la base de datos.

Esto es como yo suelo hacerlo

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() 
         }); 

Editar Esto es lo que he intentado, pero he recibido el siguiente error

no reconocido llamada a un método en SqlFunction expresión ("subcadena ", NHibernateUtil.String, new [] {Property (" Name "), Constant (Convert (1)), Constant (Convert (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))) 

     ); 

Respuesta

4

¡Puede hacerlo usando Projections.SqlGroupProjection si falla todo lo demás!

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")); 

El primer argumento es lo que está seleccionado en la selección, el segundo argumento es lo que se agrupa por, el tercer argumento es el nombre de la columna (s) que se seleccionan, y el cuarto argumento es el tipo de los datos que se están seleccionando

+0

La función de subcadena necesitaba un parámetro adicional, pero esto resolvió el problema. Muchas gracias – JConstantine

3

¿cuán grande es su lista? Si es menor de 1000 me recogería lista de elementos del servidor SQL a continuación, realice su grupo regular de consulta en la lista de

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

y luego

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

Subcadena función sería trabajar aquí, ya que su funcionamiento en C# lista no en el servidor sql

+0

En este momento estamos viendo listas con más de 20k cuentas. :( – JConstantine

3

¿Ha considerado eliminar la necesidad de la consulta de subcadena al almacenar el primer carácter del nombre en una columna separada?

Suponiendo que está utilizando SQL Server, puede hacer que sea una columna calculada persistente para evitar tener que actualizar el código que inserta/actualiza la tabla.

La posibilidad de agregar un índice que contenga esta columna también debería ayudarlo a mejorar el rendimiento de su consulta.

+0

+1 Como una solución a largo plazo, esta va a ser probablemente la forma en que tendremos que abordar este problema. mente – JConstantine