Enumerable.Todictionary apenas recupera o que precisa?
-
21-09-2019 - |
Pergunta
Estou usando enumerável.Todictionary para criar um dicionário de uma chamada LINQ:
return (from term in dataContext.Terms
where term.Name.StartsWith(text)
select term).ToDictionary(t => t.TermID, t => t.Name);
Essa chamada buscará a totalidade de cada termo ou só recuperará o termo e os campos de nome do meu provedor de dados? Em outras palavras, eu estaria salvando -me de tráfego de banco de dados se o escrevesse assim:
return (from term in dataContext.Terms
where term.Name.StartsWith(text)
select new { term.TermID, term.Name }).ToDictionary(t => t.TermID, t => t.Name);
Solução
Enumerável.Todictionary trabalha em objetos ienumerable. A primeira parte da sua declaração "(do ... Selecionar termo") é um objeto iQueryable. O consultável analisará a expressão e construirá a instrução SQL. Em seguida, ele converterá isso para um iEnumerable para passar para o TDICIário ().
Em outras palavras, sim, sua segunda versão seria mais eficiente.
Outras dicas
O SQL gerado retornará o período inteiro, para que sua segunda declaração derrubará exatamente o que você precisa.
Você pode definir dataContext.Log = Console.Out
e observe os diferentes resultados da consulta.
Usando meu banco de dados LINQPAD de amostra, aqui está um exemplo:
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();
O SQL gerado é (ou apenas espiar na guia SQL do 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]
Não. ToDictionary
é um método de extensão para IEnumerable<T>
não IQueryable<T>
. Não é preciso um Expression<Func<T, TKey>>
mas simplesmente um Func<T, TKey>
que ele chamará cegamente para cada item. Não se importa (e não sabe) sobre o LINQ e as árvores de expressão subjacente e coisas assim. Isso apenas itera a sequência e cria um dicionário. Como conseqüência, em sua primeira consulta, todas as colunas são buscadas.