Tech Brief
All About LINQ
Integrating data queries into VB and C#
Language Integrated Query (LINQ) refers to a collection of features in the Microsoft .NET 3.5 Framework that enables developers to embed queries against in-memory or external data directly into their programs. LINQ can close the gap between programming objects and data by providing a common query facility over different types of data, built into the .NET Framework.
How Does LINQ Work?
LINQ integrates query functionality into a programming language. Here are the components of LINQ:
Lambda Expressions
Lambda expressions are inline functions that operate on an input value. For example, the lambda expression "s=>s*1.10" can be read "given s, return s multiplied by 1.10." Similarly, the lambda expression "employee=>employee.Salary>50000" can be read "given employee, return whether or not employee.salary is greater than $50,000." Like delegates, lambda expressions can be passed to other methods. Unlike delegates, however, lambda expressions may be passed as expression trees (as opposed to executable IL) to other methods, giving the called method the ability to reason about the expression itself.
Query Methods
Queries are built using a set of Query Methods that are understood by the system; for example, "Select," "Where" and "OrderBy." Most of the query methods take and return strongly typed iterators (IEnumerable). A number of the query methods additionally take a delegate or lambda expression and apply it to the members of the input iterator. For example, the Where method takes a function that returns a boolean value (such as our lambda expression "employee=>employee.Salary>50000") and applies it to the input iterator, returning a new iterator containing only those values for which the function evaluated to true. Similarly, the Select method shapes an input iterator by taking a function which may return a different type (such as "employee=>employee.Salary*1.10") and applying it to the input iterator. By passing the output of the Where method as the input to the Select method, we end up with an iterator that returns the salary, increased by 10 percent, of all employees with a current salary greater than $50,000.
Extension Methods
Extension methods enable external classes to define methods that appear on instances of existing compiled classes. For example, you could define an extension method "Get
ExtendedPrice" that returned the Unitprice * Quantity on an existing class OrderItem. You could then call this method on OrderItem just like any other method. Extension methods are implemented as static methods that take an instance of an existing class as the first argument, but appear as instance methods on the existing class.
There is a public static class, System.Linq.Enumerable, that implements the standard query methods as extension methods on IEnumerable. Thus, by including the System.Linq namespace, query methods appear on any collection, array or sequence of values that implements IEnumerable.
Query Comprehensions
Queries can be built programmatically from any language by calling the query methods with the appropriate lambda expression. Query Comprehensions add keywords to C# and VB for common query operators like Select, Where, GroupBy and OrderBy, enabling common queries to be written without explicitly calling methods or specifying lambda expressions.
Anonymous Types & Object Initialization Expressions
The result of the Select operator is an IEnumerable, but it may not be convenient to define a type for every possible projection. Anonymous types can be defined inline, based on members from other structured values, without supplying names for the type or the members.
Functional Programming
LINQ expressions provide a functional definition of the desired data, rather than prescribing the procedure for yielding a set of results. The entire composed expression is not evaluated until the results are enumerated or explicitly converted to a list. The LINQ implementation chooses the best strategy for coming up with the requested results. So an implementation of LINQ over a relational store doesn't retrieve an entire table and loop through the results applying each expression individually. Instead, the entire LINQ expression gets converted into a SQL query, executed at the store via the relational engine, and the matching results are retrieved locally, with the correct projection, ordering and grouping applied.
LINQ Implementations
In addition to the default implementation of query operators over an IEnumerable, the .NET 3.5 Framework will support querying XML, relational data in SQL Server or exposed through a conceptual Entity model over extended ADO.NET data providers, and data in an ADO.NET Dataset.