LINQ is a broad set of technologies, based around (for example) a query comprehension syntax, for example:
var qry = from x in source.Foo
where x.SomeProp == "abc"
select x.Bar;
which is mapped by the compiler into code:
var qry = source.Foo.Where(x => x.SomeProp == "abc").Select(x => x.Bar);
and here the real magic starts. Note that we haven't said what Foo
is here - and the compiler doesn't care! As long as it can resolve some suitable method called Where
that can take a lambda, and the result of that has some Select
method that can accept the lambda, it is happy.
Now consider that the lambda can be compiled either into an anonymous method (delegate, for LINQ-to-Objects, which includes LINQ-to-DataSet), or to an expression-tree (a runtime model that represents the lambda in an object model).
For in-memory data (typically IEnumerable<T>
), it just executes the delegate - fine and fast. But for IQueryable<T>
the object-representation of the expression (a LambdaExpression<...>
) it can pull it apart and apply it to any "LINQ-to-Something" example.
For databases (LINQ-to-SQL, LINQ-to-Entities) this might mean writing TSQL, for example:
SELECT x.Bar
FROM [SomeTable] x
WHERE x.SomeProp = @p1
But it could (for ADO.NET Data Services, for example) mean writing an HTTP query.
Executing a well-written TSQL query that returns a small amount of data is faster that loading an entire database over the network and then filtering at the client. Both have ideal scenarios and plain-wrong scenarios, though.
The goal and benefit here is to allow you to use a single, static-checked syntax to query a wide range of data-sources, and to make the code more expressive ("traditional" code to group data, for example, isn't very clear in terms of what it is trying to do - it is lost in the mass of code).