LINQ è un ampio set di tecnologie, basate (ad esempio) su una sintassi di comprensione delle query, ad esempio:
var qry = from x in source.Foo
where x.SomeProp == "abc"
select x.Bar;
che è mappato dal compilatore in codice:
var qry = source.Foo.Where(x => x.SomeProp == "abc").Select(x => x.Bar);
e qui inizia la vera magia. Nota che non abbiamo detto cosa Foo
c'è qui - e al compilatore non importa! Finché può risolvere un metodo adatto chiamato Where
che può richiedere un lambda, e il risultato di ciò ha un Select
metodo che può accettare il lambda, è felice.
Si consideri ora che il lambda può essere compilato sia in un metodo anonimo (delegato, per LINQ-to-oggetti, che comprende LINQ to DataSet), o un'espressione-albero (un modello di esecuzione che rappresenta il lambda in un modello di oggetti ).
Per i dati in memoria (in genere IEnumerable<T>
), esegue solo il delegato, in modo corretto e veloce. Ma per IQueryable<T>
la rappresentazione dell'oggetto dell'espressione (a LambdaExpression<...>
) può separarla e applicarla a qualsiasi esempio "LINQ-to-Something".
Per i database (LINQ-to-SQL, LINQ-to-Entities) ciò potrebbe significare scrivere TSQL, ad esempio:
SELECT x.Bar
FROM [SomeTable] x
WHERE x.SomeProp = @p1
Ma potrebbe (per ADO.NET Data Services, ad esempio) significare scrivere una query HTTP.
L'esecuzione di una query TSQL ben scritta che restituisce una piccola quantità di dati è più veloce che caricare un intero database sulla rete e quindi filtrare sul client. Entrambi hanno scenari ideali e scenari chiaramente sbagliati, però.
L'obiettivo e il vantaggio qui è di consentire di utilizzare un'unica sintassi controllata statica per eseguire query su un'ampia gamma di origini dati e di rendere il codice più espressivo (il codice "tradizionale" per raggruppare i dati, ad esempio, non lo è molto chiaro in termini di ciò che sta cercando di fare - si perde nella massa di codice).