Abstract
A query is an expression that retrieves data from a data source. SQL is a query language for relational databases. XQuery is a query language for XML. LINQ (Language-Integrated Query) is a set of technologies that integrates query capabilities directly into C#. It provides language-level querying capabilities and it works across a variety of data sources.
💡 Tip
See also: https://learn.microsoft.com/en-us/dotnet/standard/linq/
Architecture
LINQ consists of:
- Extensions methods (required) –
Where
,OrderBy
,Select
, etc - LINQ providers (required) – LINQ to Objects, LINQ to Entities, LINQ to XML, LINQ to SQL
- Lambda expressions (optional) – can be used instead of named methods.
- LINQ query syntax (optional) –
from
,in
,where
,orderby
, etc.
LINQ query operations
A LINQ query operation consists of three actions:
- Obtain the data source
- Create the query (and store it in a query variable)
- Execute the query
Example:
// 1. Data source.
int[] numbers = [ 0, 1, 2, 3, 4, 5, 6 ];
// 2. Query creation
var numQuery =
from num in numbers // from clause specifies the data source
where (num % 2) == 0 // where clause applies the filter
select num; // select clause specifies the type of returned elements
// 3. Query execution
foreach (int num in numQuery)
Console.Write("{0,1} ", num);
1. The data source
Queryable types are the set of all types that implement IEnumerable<T>
or a derivative. Any queryable type is a valid LINQ data source.
If the data source is not already in memory, the LINQ provider must represent it as such.
For example, the LINQ to XML provider loads an XML document into an XElement
, which is a queryable type:
// using System.Xml.Linq;
XElement contacts = XElement.Load(@"c:\myContactList.xml");
2. The query
The query specifies what information to retrieve from the data source(s), and, optionally, how it should be sorted, grouped, or shaped before its returned.
var numQuery =
from num in numbers // from clause specifies the data source
where (num % 2) == 0 // where clause applies the filter
select num; // select clause specifies the type of returned elements
The from
, where
, and select
keywords are some of the Standard Query Operators.
LINQ queries vary in their modes of execution:
- Immediate
- Deferred
- Streaming
- Non-streaming
3. The execution
Immediate execution standard query operators
In immediate execution, the data is read and the execution is performed at once.
Examples include Count
, Max
, Average
and First
:
var evenNumQuery =
from num in numbers
where (num % 2) == 0
select num;
int evenNumCount = evenNumQuery.Count();
Additionally, any query can be forced to execute immediately using ToList
or ToArray
:
var fooQuery =
(from num in numbers
where (num % 2) == 0
select num).ToList(;)
Deferred execution standard query operators
In deferred execution, the data is ready, but execution is deferred until the resulting query variable is enumerated:
foreach (int num in numQuery)
{
// ...
}
In this mode, the query variable can be enumerated repeatedly.
Streaming standard query operators can yield result elements before all of the source data is read.
Non-streaming standard query operators must read all the data before yielding a result element.