LINQ (Language Integrated Query) to technologia wprowadzona w języku C# i innych językach platformy .NET, umożliwiająca wykonywanie zapytań do różnych źródeł danych (kolekcji, baz danych, XML, JSON itp.) w sposób deklaratywny i zintegrowany z językiem. Poniżej przykłady
JSON
string jsonData = """[
{ "name": "Adam", "active": true },
{ "name": "Ewa", "active": false },
{ "name": "Kamil", "active": true }
]""";
var jsonUsers = JsonSerializer.Deserialize<List<User>>(jsonData);
var activeUsers = from u in jsonUsers
where u.Active
select u;
Console.WriteLine("Aktywni użytkownicy:");
foreach (var user in activeUsers)
{
Console.WriteLine(user.Name);
}
Entity framework (symulacja wyników zapytania)
class User
{
public string Name { get; set; }
public int Age { get; set; }
public bool Active { get; set; }
}
List<User> users = new List<User>
{
new User { Name = "Adam", Age = 25 },
new User { Name = "Ewa", Age = 17 },
new User { Name = "Kamil", Age = 30 }
};
var adultUsers = from u in users
where u.Age > 18
select u;
Console.WriteLine("Dorośli użytkownicy:");
foreach (var user in adultUsers)
{
Console.WriteLine(user.Name);
}
XML
string xmlData = """
<library>
<book>
<title>C# in Depth</title>
<price>45</price>
</book>
<book>
<title>LINQ Unleashed</title>
<price>55</price>
</book>
</library>
""";
XDocument doc = XDocument.Parse(xmlData);
var cheapBooks = from book in doc.Descendants("book")
where (int)book.Element("price") < 50
select book.Element("title").Value;
Console.WriteLine("Tanie książki:");
foreach (var title in cheapBooks)
{
Console.WriteLine(title);
}
Kolekecje w języku C#
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var evenNumbers = from n in numbers
where n % 2 == 0
select n;
Console.WriteLine("Liczby parzyste:");
foreach (var num in evenNumbers)
{
Console.WriteLine(num);
}
Mamy dwie możliwości zapisu zapytań w technologii LINQ:
List<int> numbers = new List<int> { 1, 2, 6, 8, 3, 10, 12 };
// Query syntax
var result = from n in numbers
where n % 2 == 0 && n > 5
orderby n
select n;
foreach (var n in result)
{
Console.WriteLine(n);
}
// Method syntax
var result2 = numbers
.Where(n => n % 2 == 0 && n > 5)
.OrderBy(n => n);
foreach (var n in result2)
{
Console.WriteLine(n);
}
Wybrane operacje:
| Operacja | LINQ query syntax | Method syntax |
|---|---|---|
| Źródło danych | from x in kolekcja |
kolekcja |
| Filtrowanie | where x > 10 |
.Where(x => x > 10) |
| Sortowanie rosnąco | orderby x |
.OrderBy(x => x) |
| Sortowanie malejąco | orderby x descending |
.OrderByDescending(x => x) |
| Projekcja (wybór) | select x |
.Select(x => x) |
| Zgrupowanie | group x by x.Category |
.GroupBy(x => x.Category) |
| Zgrupowanie z aliasem | group x by x.Category into g |
.GroupBy(...) i operacje na g |
| Join (łączenie) | join y in B on x.Id equals y.Id |
.Join(B, x => x.Id, y => y.Id, (x, y) => new {...}) |
| Łączenie z lewym zewnętrznym | (brak natywnie) | .GroupJoin(...).SelectMany(...) |
| Podzapytanie pomocnicze | let wynik = ... |
.Select(x => { var wynik = ... }) |
| Zliczanie elementów | (brak) | .Count() / .Count(x => x.Warunek) |
| Suma wartości | (brak) | .Sum(x => x.Wartość) |
| Średnia wartość | (brak) | .Average(x => x.Wartość) |
| Największa wartość | (brak) | .Max(x => x.Wartość) |
| Najmniejsza wartość | (brak) | .Min(x => x.Wartość) |
| Pierwszy element | (brak) | .First() / .FirstOrDefault() |
| Ostatni element | (brak) | .Last() / .LastOrDefault() |
| Czy istnieje jakiś element | (brak) | .Any() / .Any(x => x.Warunek) |
| Czy wszystkie spełniają warunek | (brak) | .All(x => x.Warunek) |
| Czy zawiera element | (brak) | .Contains(element) |
| Unikalne wartości | (brak) | .Distinct() |
| Pominięcie elementów | (brak) | .Skip(n) |
| Pobranie pierwszych n | (brak) | .Take(n) |
| Konwersja do listy/tablicy | (brak) | .ToList(), .ToArray() |
Źródło danych musi implementować IEnumerable<T> lub IQueryable<T>
var query = list.Where(x => x > 5);
list.Add(10); // zmieniamy kolekcję po stworzeniu zapytania
foreach (var item in query)
{
Console.WriteLine(item); // wypisze 10, mimo że nie było w zapytaniu
}
var query = list.Where(x => x > 5);
Console.WriteLine(query.Count()); // pierwsza enumeracja
foreach (var item in query) { ... } // druga enumeracja
var result = list.OrderBy(x => x).Take(5); // posortuj całą kolekcję
var result = list.Take(5).OrderBy(x => x); // ogranicz dane, potem sortuj
// Zamiast skomplikowanego zpaytania
var result = list.GroupBy(x => x.Category)
.Where(g => g.Key == "A")
.SelectMany(g => g);
// Wykonaj kilka mniejszych
var grouped = list.GroupBy(x => x.Category);
var filtered = grouped.Where(g => g.Key == "A");
var result = filtered.SelectMany(g => g);
? w celu walidacji czy dana wartość nie jest nullem.var result = list.Where(x => x.Name?.StartsWith("A") == true); // Bez ? jeśli Name jest nullem zapytanie wyrzuci wyjątek NullReferenceException
var customers = context.Customers.ToList();
foreach (var customer in customers)
{
var orders = context.Orders.Where(o => o.CustomerId == customer.Id).ToList(); // N+1 zapytań
}
var customersWithOrders = context.Customers
.Include(c => c.Orders) // Funkcja dostępna w Entity Framework
.ToList(); // jedno zapytanie
Dana jest lista imion
List<string> names = new List<string> { "Anna", "Kasia", "Bartek", "Andrzej", "Krystyna" };Wypisz tylko imiona, które zaczynają się na literę „A” oraz mają więcej niż 3 znaki wykorzystując LINQ.
Dana jest lista liczb:
List<int> numbers = Enumerable.Range(1, 100).ToList();Znajdź wszystkie liczby z tej listy, które są podzielne jednocześnie przez 3 i 5 wykorzystując LINQ.
Dana jest lista produktów:
class Product { public string Name { get; set; } public double Price { get; set; } } List<Product> products = new List<Product> { new Product { Name = "Laptop", Price = 3000 }, new Product { Name = "Smartphone", Price = 2000 }, new Product { Name = "Tablet", Price = 1500 } };Posortuj produkty malejąco po cenie i wybierz tylko te, które kosztują więcej niż 1500.
List<string> names = new List<string> { "Ola", "Tomek", "Basia", "Jan", "Krzysztof", "Ela" };Pogrupuj imiona według długości (ilości znaków) i wypisz grupy (np. długość 3: Ola, Jan, Ela).
class Customer { public int Id { get; set; } public string Name { get; set; } } class Order { public int CustomerId { get; set; } public string Product { get; set; } } List<Customer> customers = new List<Customer> { new Customer { Id = 1, Name = "Adam" }, new Customer { Id = 2, Name = "Ewa" } }; List<Order> orders = new List<Order> { new Order { CustomerId = 1, Product = "Laptop" }, new Order { CustomerId = 1, Product = "Mouse" }, new Order { CustomerId = 2, Product = "Tablet" } };Wykorzystując LINQ wykonaj zapytanie któro połączy klienta z zamówieniem a następnie wypisz imię klienta z nazwąprzedmiotu który zamawiał.