techmore.in

C# - LINQ

LINQ (Language Integrated Query) in C# provides a way to query data from different sources (such as arrays, collections, databases) using a unified syntax. LINQ allows you to write queries directly in C# without needing to use SQL or other query languages. It integrates query capabilities into the C# language, making data manipulation more intuitive and expressive.

Here’s an overview of LINQ, including syntax, common operations, and examples:

1. LINQ Query Syntax

LINQ queries are written using a declarative syntax similar to SQL. They can be used to query arrays, collections, databases, XML, and more.

Basic Query Syntax

csharp
var query = from item in collection where condition select item;

2. LINQ to Objects

LINQ to Objects queries data from in-memory collections like arrays, lists, and dictionaries.

Example with Arrays

csharp
using System; using System.Linq; class Program { static void Main() { int[] numbers = { 1, 2, 3, 4, 5, 6 }; // Query syntax var evenNumbers = from number in numbers where number % 2 == 0 select number; // Method syntax var oddNumbers = numbers.Where(n => n % 2 != 0); Console.WriteLine("Even Numbers:"); foreach (var number in evenNumbers) { Console.WriteLine(number); } Console.WriteLine("Odd Numbers:"); foreach (var number in oddNumbers) { Console.WriteLine(number); } } }

3. LINQ to Collections

LINQ can be used with various collections such as List<T>, Dictionary<TKey, TValue>, and HashSet<T>.

Example with List<T>

csharp
using System; using System.Collections.Generic; using System.Linq; class Program { static void Main() { List<string> names = new List<string> { "Alice", "Bob", "Charlie", "David" }; // Query syntax var longNames = from name in names where name.Length > 4 select name; // Method syntax var shortNames = names.Where(n => n.Length <= 4); Console.WriteLine("Names with more than 4 characters:"); foreach (var name in longNames) { Console.WriteLine(name); } Console.WriteLine("Names with 4 or fewer characters:"); foreach (var name in shortNames) { Console.WriteLine(name); } } }

4. LINQ to SQL/Entity Framework

LINQ can also be used to query databases when using Object-Relational Mapping (ORM) tools like Entity Framework.

Example with Entity Framework

csharp
using System; using System.Linq; using Microsoft.EntityFrameworkCore; public class ApplicationContext : DbContext { public DbSet<Person> People { get; set; } } public class Person { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } } class Program { static void Main() { using (var context = new ApplicationContext()) { var adults = from person in context.People where person.Age >= 18 select person; foreach (var person in adults) { Console.WriteLine($"{person.Name}, {person.Age} years old"); } } } }

5. Common LINQ Operations

Select - Projects each element of a sequence into a new form.

csharp
var names = new List<string> { "Alice", "Bob", "Charlie" }; var nameLengths = names.Select(name => name.Length);

Where - Filters a sequence of values based on a predicate.

csharp
var numbers = new List<int> { 1, 2, 3, 4, 5 }; var evenNumbers = numbers.Where(n => n % 2 == 0);

OrderBy and OrderByDescending - Sorts a sequence in ascending or descending order.

csharp
var sortedNumbers = numbers.OrderBy(n => n); var reverseSortedNumbers = numbers.OrderByDescending(n => n);

GroupBy - Groups the elements of a sequence by a specified key.

csharp
var people = new List<Person> { new Person { Name = "Alice", Age = 25 }, new Person { Name = "Bob", Age = 30 }, new Person { Name = "Charlie", Age = 25 } }; var groupedByAge = people.GroupBy(p => p.Age); foreach (var group in groupedByAge) { Console.WriteLine($"Age: {group.Key}"); foreach (var person in group) { Console.WriteLine($" {person.Name}"); } }

Join - Joins two sequences based on a key.

csharp
var students = new List<Student> { new Student { Id = 1, Name = "Alice" }, new Student { Id = 2, Name = "Bob" } }; var grades = new List<Grade> { new Grade { StudentId = 1, Course = "Math", GradeValue = "A" }, new Grade { StudentId = 2, Course = "English", GradeValue = "B" } }; var studentGrades = from student in students join grade in grades on student.Id equals grade.StudentId select new { student.Name, grade.Course, grade.GradeValue }; foreach (var item in studentGrades) { Console.WriteLine($"{item.Name} - {item.Course}: {item.GradeValue}"); }

Aggregate - Applies an accumulator function over a sequence.

csharp
var numbers = new List<int> { 1, 2, 3, 4, 5 }; var sum = numbers.Aggregate((total, next) => total + next);

6. Deferred vs. Immediate Execution

  • Deferred Execution: LINQ queries are not executed when they are defined but rather when they are iterated over. This allows for optimization and composition of queries.

  • Immediate Execution: Methods like ToList(), ToArray(), and Count() force immediate execution of the query.

Example of Deferred Execution

csharp
var numbers = Enumerable.Range(1, 10).Where(n => n % 2 == 0); Console.WriteLine(numbers.Count()); // Query executes here

Summary

LINQ is a powerful feature of C# that provides a unified way to query various data sources. It allows for expressive and readable code through both query and method syntax. LINQ operations include filtering, projection, sorting, grouping, joining, and aggregation. Whether working with in-memory collections or querying databases with Entity Framework, LINQ can greatly enhance productivity and maintainability in your C# applications.