LINQ é um amplo conjunto de tecnologias, baseado em (por exemplo) uma sintaxe de compreensão de consulta, por exemplo:
var qry = from x in source.Foo
where x.SomeProp == "abc"
select x.Bar;
que é mapeado pelo compilador em código:
var qry = source.Foo.Where(x => x.SomeProp == "abc").Select(x => x.Bar);
e aqui começa a verdadeira magia. Observe que não dissemos o que Foo
está aqui - e o compilador não se importa! Contanto que ele possa resolver algum método adequado chamado Where
que possa receber um lambda, e o resultado disso tenha algum Select
método que possa aceitar o lambda, ele está feliz.
Agora, considere que o lambda pode ser compilado tanto em um método anônimo (delegado, para LINQ-to-Objects, que inclui LINQ to DataSet), ou a uma expressão-árvore (um modelo de execução que representa o lambda em um modelo de objeto )
Para dados na memória (normalmente IEnumerable<T>
), ele apenas executa o delegado - bem e rápido. Mas, para IQueryable<T>
a representação de objeto da expressão (a LambdaExpression<...>
), ele pode separá-la e aplicá-la a qualquer exemplo "LINQ-to-Something".
Para bancos de dados (LINQ-to-SQL, LINQ-to-Entities), isso pode significar escrever TSQL, por exemplo:
SELECT x.Bar
FROM [SomeTable] x
WHERE x.SomeProp = @p1
Mas pode (para ADO.NET Data Services, por exemplo) significar escrever uma consulta HTTP.
Executar uma consulta TSQL bem escrita que retorna uma pequena quantidade de dados é mais rápido do que carregar um banco de dados inteiro pela rede e, em seguida, filtrar no cliente. Ambos têm cenários ideais e cenários totalmente errados.
O objetivo e o benefício aqui é permitir que você use uma única sintaxe com verificação estática para consultar uma ampla gama de fontes de dados e tornar o código mais expressivo (código "tradicional" para agrupar dados, por exemplo, não é muito claro em termos do que está tentando fazer - está perdido na massa do código).