LINQ (Language-Integrated Query) (read as Link) in C# is a powerful feature that allows you to query and manipulate data from different data sources using a syntax similar to SQL queries.
There are two ways to write LINQ queries. You can choose either way, usually we prefer Query expression for lengthy queries.
1. Query Expressions
var numbers = new List<int> { 1, 2, 3, 4, 5 };
var evenNumbers = from num in numbers where num % 2 == 0
select num;
2. LINQ Methods (Fluent Syntax)
var evenNumbers=numbers.Where(x=> x.num%2==0);
LINQ (Language-Integrated Query) methods can be used with classes that implement the IEnumerable<T>
or IQueryable<T>
interfaces. These interfaces define the ability to enumerate over a collection of objects (IEnumerable<T>
) or to perform query operations (IQueryable<T>
).
Let’s understand why it is useful feature by writing a code block without the use of LINQ query.
Prior to LINQ , in the below scenario you loop through the list and
List<Person> people = GetPeople();
List<string> peopleOver18InDelhi= new List<string>();
// Traditional approach without LINQ
foreach (Person person in people)
{
if (person.Age >= 18 && person.City == "Delhi")
{
peopleOver18InDelhi.Add(person.Name);
}
}
The same can be written in LINQ like this
var peopleOver18InDelhi= people
.Where(person => person.Age >= 18 && person.City == "Delhi")
.Select(person => person.Name)
.ToList();// This executes the code immediately.
You can clearly see the difference now.
a. Readability- LINQ query is readable and concise.
b. Use of chaining- LINQ provides a fluent API (Where
, Select
) that allows chaining operations. You can add additional operations (like sorting or grouping) easily without restructuring loops and conditionals.
However, In terms of performance, you need to understand two things.
1 LINQ query in most cases perform similar to its Non LINQ way or little poorer than that of traditional way if you use it with method like ToList() which executes the code immediately.
2. LINQ has deferred execution feature , meaning that queries are executed only when the result is actually enumerated (e.g., during iteration or when calling ToList()
). This allows LINQ to optimize query execution and defer resource-intensive operations until necessary, potentially improving performance and reducing memory overhead, especially when dealing with large datasets.. For example, the below code will return IEnumerable<string> if you remove ToList(). This code is just like a query which is not executed. It will get executed only when you iterate through the list or call ToList(). It can be helpful if you don’t want to process it immediately and want to do later in the code (deferring the execution)
var peopleOver18InDelhi= people
.Where(person => person.Age >= 18 && person.City == "Delhi")
.Select(person => person.Name)
Types of LINQ based on DataSource
1. LINQ to Objects
Purpose: Querying in-memory data structures such as arrays, lists, collections, and other IEnumerable<T> types.
Usage: Allows you to perform queries using LINQ operators (Where
, Select
, OrderBy
, etc.) directly on objects in memory.
Example: Refer to above examples
2. LINQ To XML
Purpose: Querying and manipulating XML data.
Usage: Provides XML-specific query operators (Descendants
, Elements
, Attributes
, etc.) to navigate XML documents.
3. LINQ To SQL (or LINQ To Entities)
Purpose: Querying data using Entity Framework (an ORM – Object-Relational Mapping) that supports LINQ.
Usage: Provides an object-oriented way to query and manipulate data stored in relational databases.
4. LINQ To Dataset
Purpose: Querying datasets and data tables in ADO.NET.
Usage: Provides LINQ query capabilities for working with DataTables and DataSets.
Example:
var result = from row in dataSet.Tables["People"].AsEnumerable()
where (int)row["Age"] > 18
select row["Name"];
5. Parallel LINQ (PLINQ)
Purpose: Performing parallel queries to leverage multi-core processors.
Usage: Enhances LINQ queries with parallel execution, automatically parallelizing operations for improved performance on large datasets.
Example:
var result = from person in people.AsParallel()
where person.Age > 18
select person.Name;