2011-06-17 10 views
6

Estoy tratando de obtener un recuento total de registros del siguiente método utilizando EntityFramework y Linq. Es lento devolver un conteo.Linq Seleccionar instrucción lenta al obtener COUNT

public static int totalTracking(int id) 
{ 
    using (var ctx = new GPEntities()) 
    { 
     var tr = ctx.Tracking 
        .Where(c => c.clientID == Config.ClientID) 
        .Where(c => c.custID == id) 
        .Where(c => c.oOrderNum.HasValue) 
        .ToList(); 
     return tr.Count(); 
    }   
} 
+1

Aquí está una manera de acelerarlo, combina las consultas .Where en una. Acabo de leer un artículo sobre esto en realidad. http://msmvps.com/blogs/jon_skeet/archive/2011/06/16/linq-to-objects-and-the-performance-of-nested-quot-where-quot-calls.aspx?utm_source=feedburner&utm_medium = feed & utm_campaign = Feed% 3A + JonSkeetCodingBlog +% 28Jon + Skeet% 27s + Codificación + Blog% 29 – m4tt1mus

Respuesta

10

Se puede simplificar significativamente la consulta:

using (var ctx = new GPEntities()) 
{ 
    return ctx.Tracking 
     .Where(c => c.clientID == Config.ClientID) 
     .Where(c => c.custID == id) 
     .Where(c => c.oOrderNum.HasValue) 
     .Count(); 
} 

Cuando se llama a ToList esto desencadenará materialización, por lo que la consulta será emitido a la base de datos y se recuperará todas las columnas. El conteo real ocurriría en el cliente.

Si lo hace solo Count, sin ToList emitirá una consulta cuando llame al Count y el servidor devolverá un solo número, en lugar de una tabla.

Esto no es tan crítico para el rendimiento, pero creo que el código sería un poco más agradable sin que muchos Where:

using (var ctx = new GPEntities()) 
{ 
    return ctx.Tracking 
     .Where(c => 
      c.clientID == Config.ClientID && 
      c.custID == id && 
      c.oOrderNum.HasValue) 
     .Count(); 
} 

o incluso

using (var ctx = new GPEntities()) 
{ 
    return ctx.Tracking 
     .Count(c => 
      c.clientID == Config.ClientID && 
      c.custID == id && 
      c.oOrderNum.HasValue); 
} 
+0

Hombre - Acabo de ver eso .ToList() - gracias! Tu código está funcionando –

+0

Supongo que no se pueden obtener ideas al discutirlo, pero prefiero no hacer expresiones compuestas AND en Where-lambdas. Encuentro que facilita agregar/eliminar condiciones cuando puede hacer un shift + del o agregar una nueva línea, y hace que sea más fácil distinguir entre predicados no realimentados. – kai

2

quitar la llamada .ToList(). Obliga a la consulta a llevar los resultados completos al cliente.

Quitando esto, y sólo llamar .Count() directamente en los resultados de tr (sin ToList()), el Count() se convierte en parte de la propia consulta, y ejecutado de forma remota, lo que simplificará dramáticamente este:

public static int totalTracking(int id) 
{ 
    using (var ctx = new GPEntities()) 
    { 
     var tr = ctx.Tracking 
      .Where(c => c.clientID == Config.ClientID) 
      .Where(c => c.custID == id) 
      .Where(c => c.oOrderNum.HasValue); 

     // This can be added above, or left here - the end result is the same 
     return tr.Count(); 
    }   
} 
3

se puede simplificar enormemente las cosas y sólo tiene que utilizar el Count Extension method

Ha intentado:

public static int totalTracking(int id) 
{ 
    using (var ctx = new GPEntities()) 
    { 
     return ctx.Tracking.Count(
        c => c.clientID == Config.ClientID && 
         c.custID == id && 
         c.oOrderNum.HasValue); 
    }   
} 
+0

BTW - Enlace de método de extensión incorrecto - pruebe http://msdn.microsoft.com/en-us/library/bb534807.aspx en su lugar ... –

+0

@Reed Copsey thxs, si Microsoft dejara de jugar con su documentación, respondería Las preguntas de StackOverflow son mucho más fáciles :) – Nix

+0

@Nik: No hay problema, la que tenía era para IEnumerable, no IQueryable;) –