LInq

LINQ w C# – kompletny przewodnik z przykładami i najlepszymi praktykami

LINQ w C# – kompletny przewodnik z przykładami i najlepszymi praktykami

LINQ w C# (Language Integrated Query) to jedno z tych narzędzi, które realnie zmieniają sposób myślenia o danych. Umożliwia czytelne, deklaratywne i bezpieczne typowo przetwarzanie kolekcji, baz danych, XML, JSON czy danych z API – bez opuszczania języka C#. W tym artykule poznasz czym jest LINQ, jak działa, gdzie go używać oraz zobaczysz praktyczne przykłady LINQ w realnych scenariuszach projektowych.

Czym jest LINQ (Language Integrated Query)?

LINQ (Language Integrated Query) to rozszerzenie języka C# wprowadzone przez Microsoft, które pozwala wykonywać zapytania do danych bezpośrednio w kodzie, przy użyciu jednolitej składni.

Zamiast:

  • pętli foreach
  • instrukcji warunkowych
  • ręcznego mapowania danych

otrzymujesz deklaratywne zapytania, podobne do SQL, ale w pełni typowane i sprawdzane na etapie kompilacji.


Dlaczego LINQ jest tak popularny w .NET?

Jednolita składnia zapytań

Te same operatory (Where, Select, GroupBy) działają:

  • na kolekcjach w pamięci (List<T>)
  • w Entity Framework
  • na XML
  • na JSON
  • na danych z API

Silne typowanie

Błędy typów wykrywane są w czasie kompilacji, a nie dopiero w runtime.

IntelliSense i refaktoryzacja

Visual Studio rozumie LINQ – podpowiada metody, wykrywa błędy, wspiera refaktoryzację.

Czytelność i testowalność

Kod oparty o LINQ:

  • jest krótszy
  • łatwiejszy do testowania
  • prostszy w utrzymaniu

Składnia LINQ – dwie drogi, ten sam cel

LINQ Method Syntax (najczęściej używana)

var adults = people.Where(p => p.Age > 25);

LINQ Query Syntax (bardziej SQL-owa)

var adults =
    from p in people
    where p.Age > 25
    select p;

Technicznie obie formy są równoważne – kompilator zamienia Query Syntax na Method Syntax.

Oto kilka przykładów zastosowania LINQ w różnych scenariuszach:

Filtrowanie danych (Where)

Wyszukaj osoby w kolekcji, które mają więcej niż 25 lat.

var adults = people.Where(person => person.Age > 25);

Używaj do:

  • walidacji
  • filtrów użytkownika
  • logiki biznesowej

Sortowanie (OrderBy, ThenBy)

Posortuj listę produktów według ceny.

var sortedProducts = products
      .OrderBy(p => p.Price)
      .ThenBy(p => p.Name);

Pobieranie fragmentu danych (Take, Skip)

var top5Products = products.Take(5);

Idealne do:

  • paginacji
  • dashboardów
  • API

Grupowanie (GroupBy)

Pogrupuj osoby według miasta zamieszkania.

var groupedByCity = people.GroupBy(p => p.City);

Agregacje (Count, Sum, Average, Max)

int count = people.Count(p => p.Age > 18);
double avg = numbers.Average();
int max = numbers.Max();

Łączenie danych:

Połącz listę zamówień z klientami w oparciu o identyfikator klienta.

var joinedData = orders.Join(
   customers, 
   order => order.CustomerId, 
   customer => customer.Id, 
   (order, customer) => new 
  { 
     order.Id, 
     customer.Name,
     order.TotalValue 
   });

Najczęstsze zastosowanie:

  • relacje 1-N
  • raporty
  • DTO do API

Pobieranie konkretnej ilości elementów:

Pobierz pierwszych 5 produktów z listy.

var top5Products = products.Take(5);

Pobieranie unikalnych elementów:

Pobierz unikalne miasta z listy zamówień.

var uniqueCities = orders.Select(order => order.City).Distinct();

Zliczanie elementów w kolekcji:

Oblicz, ile osób w kolekcji ma wiek powyżej 18 lat.

int adultCount = people.Count(person => person.Age > 18);

Agregacja danych:

Oblicz sumę, średnią lub maksimum wartości w kolekcji.

int sum = numbers.Sum();
double average = numbers.Average();
int max = numbers.Max();

Filtrowanie danych zagnieżdżonych:

Wybierz wszystkie książki napisane przez autora o nazwisku “Smith”.

var booksBySmith = library
   .Where(author => author.Name == "Smith")
   .SelectMany(author => author.Books);

Działania na elementach w kolekcji:

Dodaj 10 do każdej wartości w liście.

var updatedList = numbers.Select(number => number + 10).ToList();

Wyszukiwanie wzorców:

Wyszukaj słowa rozpoczynające się na literę “A” w liście słów.

var wordsStartingWithA = words
  .Where(word => word.StartsWith("A", StringComparison.OrdinalIgnoreCase));

Operacje na danych XML:

Analiza danych XML w celu wydobycia potrzebnych informacji.

var query = from element in xmlDocument.Descendants("Book")
            where (int)element.Element("Price") > 20
            select element.Element("Title").Value;

Operacje na bazie danych SQL:

Użyj LINQ to SQL do wykonywania zapytań do bazy danych SQL.

var highValueOrders = dbContext.Orders
    .Where(order => order.TotalValue > 1000);

Zapytania do danych JSON:

Analiza danych w formacie JSON.

var highIncomeCustomers = jsonCustomers
    .Where(customer => customer["Income"]
    .Value<int>() > 50000);

Zastosowanie dynamicznego LINQ:

Tworzenie zapytań w sposób dynamiczny, na przykład na podstawie warunków użytkownika.

var filteredData = data.Where("Age > 30 && City == \"New York\"");

Wykonywanie operacji równoległych:

Wykonanie operacji LINQ na wielu wątkach w celu zwiększenia wydajności.

var parallelQuery = data.AsParallel().Where(item => item.Value > 50);

Tworzenie zapytań skomplikowanych i bardziej zaawansowanych:

Kombinowanie różnych operacji LINQ, aby uzyskać bardziej skomplikowane wyniki.

var result = from order in orders
             join customer in customers on order.CustomerId equals customer.Id
             where customer.Country == "USA"
             group order by order.Product into productGroup
             select new
             {
                 Product = productGroup.Key,
                 TotalSales = productGroup.Sum(o => o.Quantity)
             };

Analiza tekstu:

Wydobądź unikalne słowa z tekstu i posortuj je według liczby wystąpień.

string text = "To jest przykład zastosowania LINQ w analizie tekstu. LINQ to potężne narzędzie.";
var uniqueWords = text.Split(' ')
                    .Select(word => word.ToLower())
                    .Where(word => !string.IsNullOrWhiteSpace(word))
                    .GroupBy(word => word)
                    .OrderByDescending(group => group.Count())
                    .Select(group => $"{group.Key}: {group.Count()}");

Znajdowanie palindromów:

Znajdź wszystkie palindromy w danej kolekcji słów.

var palindromes = words.Where(word => word.SequenceEqual(word.Reverse()));

Analiza logów:

Wykorzystaj LINQ do analizy logów zapisywanych w plikach lub bazach danych. Na przykład, znajdź wszystkie logi błędów w danym okresie czasu.

var errorLogs = logs
.Where(log => log.LogType == LogType.Error 
&& log.Timestamp >= startTime 
&& log.Timestamp <= endTime);

Tworzenie generowania fraz acronimów:

Przetwórz listę fraz na akronimy.

var phrases = new List<string> 
{ "Language Integrated Query", "World Wide Web", "Artificial Intelligence" };
var acronyms = phrases
.Select(phrase => new string(phrase.Split(' ')
.Select(word => word[0]).ToArray()));

Pobieranie danych geograficznych:

Wykorzystaj LINQ do pobrania danych geograficznych, takich jak kody pocztowe i koordynaty geograficzne, z zewnętrznego źródła, takiego jak API usług geolokalizacyjnych.

var locations = geolocationService.GetLocations()
.Where(location => location.ZipCode.StartsWith("90") 
&& location.Latitude > 40);

Zastosowanie LINQ w grach:

W grach można użyć LINQ do zarządzania danymi dotyczącymi postaci, przedmiotów itp. Na przykład, wybierz wszystkie przedmioty w grze, których poziom jest wyższy niż poziom postaci.

var highLevelItems = gameItems.Where(item => item.RequiredLevel > player.Character.Level);
  • Analiza mediów społecznościowych: Jeśli pracujesz nad projektem związanym z mediami społecznościowymi, możesz użyć LINQ do analizy postów i komentarzy, na przykład, aby znaleźć najpopularniejsze treści lub identyfikować wpisy z negatywnymi komentarzami.
  • Rozwiązywanie łamigłówek: Stwórz program do rozwiązywania łamigłówek logicznych, takich jak sudoku, wykorzystując LINQ do generowania i analizy planszy.
  • Automatyzacja pracy biurowej: Przy użyciu LINQ, automatyzuj pracę biurową, na przykład przeszukując i analizując dane w arkuszach kalkulacyjnych lub dokumentach tekstowych.
  • Rekomendacje i analiza zachowań użytkowników: W aplikacjach internetowych i sklepach internetowych użyj LINQ do analizy zachowań użytkowników i generowania rekomendacji produktów.

Te oryginalne przykłady ilustrują, jak LINQ może być używane w różnych dziedzinach, aby przyspieszyć i ułatwić analizę i manipulację danymi. LINQ jest bardzo elastycznym narzędziem i może być dostosowane do wielu różnych zastosowań.

Najlepsze praktyki LINQ w C#

Checklist:

  • ✅ Nie wywołuj ToList() zbyt wcześnie
  • ✅ Czytaj zapytania jak zdania
  • ✅ Oddziel LINQ od logiki biznesowej
  • ✅ Uważaj na LINQ w pętlach
  • ✅ Profiluj zapytania EF (ToQueryString())

Kiedy NIE używać LINQ?

  • bardzo krytyczne fragmenty performance
  • ekstremalnie złożone algorytmy
  • kod wymagający pełnej kontroli iteracji

Czasem zwykła pętla for jest… po prostu lepsza.

Oto kilka kluczowych cech LINQ:

  • Jednolita składnia: LINQ wprowadza jednolitą składnię do wykonywania zapytań, niezależnie od źródła danych. Programiści mogą używać tych samych konstrukcji języka C# do przetwarzania różnych rodzajów danych.
  • Typowanie: LINQ jest silnie zintegrowany z typami danych języka C#, co oznacza, że błędy typu można wykrywać na etapie kompilacji, co pomaga w uniknięciu błędów w trakcie działania programu.
  • Wsparcie dla różnych źródeł danych: LINQ obsługuje wiele rodzajów źródeł danych, takich jak tablice, listy, kolekcje, bazy danych, pliki XML i inne.
  • IntelliSense: LINQ w językach programowania .NET jest zintegrowany z narzędziami programistycznymi, takimi jak Visual Studio, co umożliwia korzystanie z funkcji IntelliSense do automatycznego uzupełniania zapytań LINQ i dostarczania sugestii podczas programowania.
  • Wydajność optymalizowana: LINQ stara się optymalizować zapytania tak, aby były wydajne. Możesz kontrolować sposób, w jaki LINQ przetwarza zapytania i w jaki sposób są wykonywane.
  • Rozszerzalność: Możesz tworzyć własne rozszerzenia LINQ i operatory, aby dostosować go do swoich potrzeb.
  • Zapytania składane: Można łączyć wiele operatorów LINQ w jednym zapytaniu, tworząc bardziej zaawansowane zapytania. LINQ umożliwia budowanie zapytań skomplikowanych w sposób modułowy.
  • Wsparcie dla anonimowych typów: LINQ pozwala na tworzenie anonimowych typów, które są przydatne w sytuacjach, gdy chcesz zwrócić zestaw właściwości z różnych źródeł danych.
  • Zapytania asynchroniczne: LINQ obsługuje również zapytania asynchroniczne, co jest przydatne w aplikacjach, które korzystają z asynchronicznego programowania.
  • Zapytania wyrażeniowe: Można używać wyrażeń LINQ, które są bardziej czytelne niż tradycyjne zapytania.
  • Obsługa języka SQL: W przypadku baz danych można używać LINQ to SQL lub Entity Framework do wykonywania zapytań LINQ w języku SQL na bazie danych.

LINQ (Language Integrated Query) znajduje zastosowanie w wielu różnych kontekstach, zarówno dla kolekcji w pamięci, jak i dla różnych źródeł danych, takich jak bazy danych i XML.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *