No solamente Enumerable.ToDictionary recuperar lo que necesita?
-
21-09-2019 - |
Pregunta
Estoy usando Enumerable.ToDictionary para crear un diccionario al lado de una llamada LINQ:
return (from term in dataContext.Terms
where term.Name.StartsWith(text)
select term).ToDictionary(t => t.TermID, t => t.Name);
¿Será que la llamada se ha podido recuperar la totalidad de cada término, o será sólo recuperar el los campos Nombre de mi proveedor de datos y TermID? En otras palabras, ¿estaría ahorrando mismo tráfico de la base de datos si por el contrario lo escribí así:
return (from term in dataContext.Terms
where term.Name.StartsWith(text)
select new { term.TermID, term.Name }).ToDictionary(t => t.TermID, t => t.Name);
Solución
Enumerable.ToDictionary funciona en objetos IEnumerable. La primera parte de su declaración "(de ... seleccione término") es un objeto IQueryable. Consultable se va a ver en la expresión y la construcción de la instrucción SQL. A continuación, convertir que a un IEnumerable para pasar a ToDictionary ().
En otras palabras, sí, su segunda versión sería más eficiente.
Otros consejos
El SQL generado devolverá la totalidad del plazo, por lo que su segunda declaración hará bajar justo lo que necesita.
Puede establecer dataContext.Log = Console.Out
y mirar los diferentes resultados de la consulta.
Uso de mi base de datos LINQPad muestra, he aquí un ejemplo:
var dc = (TypedDataContext)this;
// 1st approach
var query = Orders.Select(o => o);
dc.GetCommand(query).CommandText.Dump();
query.ToDictionary(o => o.OrderID, o => o.OrderDate).Dump();
// 2nd approach
var query2 = Orders.Select(o => new { o.OrderID, o.OrderDate});
dc.GetCommand(query2).CommandText.Dump();
query2.ToDictionary(o => o.OrderID, o => o.OrderDate).Dump();
El SQL generado es (o simplemente vistazo a la pestaña SQL de LINQPad):
// 1st approach
SELECT [t0].[OrderID], [t0].[OrderDate], [t0].[ShipCountry]
FROM [Orders] AS [t0]
// 2nd approach
SELECT [t0].[OrderID], [t0].[OrderDate]
FROM [Orders] AS [t0]
No. ToDictionary
es un método de extensión para IEnumerable<T>
no IQueryable<T>
. No hace falta ser un Expression<Func<T, TKey>>
sino simplemente un Func<T, TKey>
que va a llamar a ciegas para cada elemento. No le importa (y no sabe) sobre LINQ y los árboles de expresión subyacentes y cosas por el estilo. Es simplemente itera la secuencia y se acumula un diccionario. Como consecuencia de ello, en su primera consulta, todas las columnas se recuperan.