2010-08-26 12 views
11

que tipo de captar toda retrasado el concepto de ejecución, pero los siguientes me ha intrigado ...Slow foreach() en una consulta LINQ - ToList() aumenta enormemente el rendimiento. ¿Por qué es esto?

En un DataTable que contiene aproximadamente 1000 filas, llamo AsEnumerable(). Luego selecciono las entidades devueltas a un IEnumerable de clases fuertemente tipadas (1) ... Aquí es donde me confundo: hago un ciclo foreach en la colección; seleccionando cosas de los elementos individuales en la colección usando un grupo de Donde() llama al (2) ... Y está muerto lento.

  1. DataTable.AsEnumerable().Select(r => new ObjectRepresentation { ... });
  2. item.Where(i => i.SomeEnum == SomeEnum.Something)


... Pero si llamo ToList() justo después de mi AsEnumerable() llamada en el DataTable, el foreach el bucle tarda menos de un segundo en completarse.

¿Qué me falta aquí? ¿Estoy efectivamente llamando al AsEnumerable() cada vez que mi ciclo itera? ¿O cada vez que accedo a un artículo en la colección? O cada vez que hago un ¿Dónde() llama a un artículo en la colección? O todo lo de arriba?


actualización

código Algo completa:

public class ObjectRepresentation 
{ 
    public SomeEnum SomeEnum { get; set; } 
} 


var collection = DataTable.AsEnumerable().Select(r => new ObjectRepresentation 
{ 
    SomeEnum = (SomeEnum)Convert.ToInt32(r["SomeEnum"]) 
}); 

foreach(var item in collection) // slow loop 
{ 
    // 10 or so Where() calls on item inside this loop 
} 

collection = collection.ToList(); // Hit hyper speed button! 

foreach(var item in collection) // fast loop 
{ 
    // 10 or so Where() calls on item inside this loop 
} 
+3

Parece que está haciendo una llamada a la base de datos en cada iteración. Puede ejecutar el Analizador de SQL para ver si eso es cierto ... –

+0

¿Por qué llamar a AsEnumerable()? AsEnumerable cambia un objeto en tiempo de compilación a IEnumerable si ya implementa IEnumerable . ¿Por qué no iterar las filas usando la propiedad Filas de una tabla? – Wix

+1

@Wix: 'DataTable' aún no implementa' IEnumerable '. Cuando llamas a 'AsEnumerable' en' DataTable' estás llamando al método 'DataTableExtensions.AsEnumerable', * not *' Enumerable.AsEnumerable'. http://msdn.microsoft.com/en-us/library/system.data.datatableextensions.asenumerable.aspx – LukeH

Respuesta

7

No va a obtener todos los elementos de la base de datos hasta que escriba

ToList or First or Single 

En foreach, se envía una consulta en la base de datos para cada elemento. Por lo tanto, funciona más lento. Abra su generador de perfiles sql para comprender mejor.

+1

En el escenario particular del OP, puede estar causando que se realice una consulta de base de datos para cada registro iterado, pero * no * es cierto en general que al enumerar una consulta diferida con foreach consultará cada elemento por separado. Toda la colección se obtiene cuando se utiliza por primera vez el enumerador. –

+2

Está consultando una tabla de datos, no un DataContext Linq u ObjectContext. No hay forma de que una consulta en la tabla de datos haga que una consulta DB ejecute –

+2

sí, tiene razón. Pero esta es una explicación general para entender lo que hace linq con los métodos. Para cada elemento, tomará más tiempo obtener datos que usar ToList antes para cada declaración. – NetSide

10

No entiende qué métodos son diferidos y cuáles no, por lo que no entiende cuando el código define las operaciones vs realiza operaciones.

Todo esto se aplazó. Definen, pero no ejecutan, una operación.

source.AsEnumerable 
source.Select 
source.Where 

Enumeran la fuente y no se difieren.

source.ToList 
source.First 
source.Single 
foreach(var x in source) 
+1

¿Puedes elaborar? – roosteronacid

+4

Sí puedo. ¿En que? –

0

De hecho, parece que no tiene una idea clara de qué es la ejecución del código y cuál es la definición de la intención de (posiblemente) ejecutar más adelante cuando los resultados se utilizan realmente. Sugiero leer uno esta parte de LINQ.

Y posiblemente intente ejecutar sus dos variantes con un depurador conectado para que pueda ver qué código se está ejecutando, en qué orden y qué está pasando con sus datos. Puede que te sorprenda (¿grande?) Aquí ...

Cuestiones relacionadas