2009-08-10 8 views
5

¿Cuál es la diferencia entre estas dos afirmaciones:LINQ: Diferencia entre 'Seleccionar c' y 'Seleccionar nueva (c ...'

var result = from c in context.CustomerEntities 
join p in context.ProjectEntities on c.Pk equals p.CustomerPk 
where p.Entered > DateTime.Now.AddDays(-15) 
select c; 

y

var result = from c in context.CustomerEntities 
join p in context.ProjectEntities on c.Pk equals p.CustomerPk 
where p.Entered > DateTime.Now.AddDays(-15) 
select new (c.Company, c.Entered, c.pk); 

¿Hay alguna cuestión relacionada con el rendimiento en estos estados. (Por simplicidad C contiene sólo estos 3 coloums.)

Gracias.

Respuesta

10

¿Cuál es la diferencia entre estos dos estados

Los primeros devuelve una secuencia filtrada del objeto de origen original/completa; el segundo todavía hace el filtro, pero devuelve una secuencia de tipo anónimo con solo esas tres propiedades.

¿Hay alguna cuestión relacionada con el rendimiento en estas declaraciones

El rendimiento depende del back-end. Si esto es LINQ-to-Objects, entonces con new {...} está creando objetos adicionales (tipos anónimos) por registro, por lo que puede haber una sobrecarga muy pequeña. Sin embargo, si esto es LINQ-to-SQL, etc. (un back-end de base de datos), este puede ser un gran beneficio . El generador de consultas comprobará qué columnas son necesarias y solo obtendrá las tres en su tipo de anon; si tiene (por ejemplo) un BLOB (o solo un largo varchar) en sus datos que no necesita, esto puede ser un gran beneficio de .

Notas adicionales: no se pueden incluir los tipos anónimos en la firma de un método, por lo que podrían encontrar que tienen que declarar su propio tipo DTO para este propósito:

return new CustomerDto { Company = c.Company, Entered = c.Entered, PK = c.pk}; 
... 
public class CustomerDto { ... } 
+1

+1 para la respuesta genérica, pero en su situación devuelve todas las columnas de todos modos. – cjk

+0

Sí, ck es correcto, estoy devolviendo todas las columnas. – Waheed

1

en caso de duda, el perfil.

Pero sí, creo que hay una sobrecarga de rendimiento. Si lo hace select c, la colección contendrá referencias a los artículos originales. Si lo hace select new { ... }, entonces C# está construyendo un tipo anónimo para usted, creando nuevas instancias de ese tipo y llenándolas con datos. Suena definitivamente más lento para mí.

+0

+1 para recomendar el perfilado. – Marcel

2

La principal diferencia es que el primer ejemplo devuelve referencias a instancias existentes, mientras que el segundo ejemplo crea nuevas instancias de tipo anónimo. Me preocuparía más este tema que cualquier posible problema de rendimiento.

2

me encontré con algunas pruebas (usando Cronógrafo). En ningún caso los tipos anónimos fueron más rápidos, en Linq-to-SQL (contra SQL Server), Linq-to-Entities (contra MySQL) y Linq-to-Objects (contra una Lista). De hecho, generalmente era más lento, dependiendo de la cantidad de columnas que seleccione.

Uno de mis resultados: Ejecuto cada consulta 5000 veces contra una tabla de 5 columnas pobladas por 400 filas con Linq-to-Entities.

objeto anónimo (seleccionar 1 columna): 17314ms

objeto anónimo (seleccionando 5 columnas): 19193ms objeto

fuente: 16055ms

De todos modos, la mejor manera de averiguarlo es para probarlo usted mismo (toma más o menos el tiempo para escribir una buena publicación).