Wat is een LINQ query syntax?

LINQ Query Syntax is SQL-achtige manier om gegevens te bevragen in C#. Het biedt een gestructureerde manier om collecties, databases en andere gegevensbronnen te filteren, sorteren en transformeren.

Hoe zit LINQ query syntax in elkaar?

LINQ (Language Integrated Query) biedt een query-gebaseerde manier om data te filteren, groeperen en transformeren binnen C#. Query Syntax is een van de twee manieren om LINQ te schrijven en lijkt sterk op SQL.

Bij LINQ Query Syntax gebruik je keywords zoals from, where, select en orderby om gegevens uit een bron (zoals een lijst of database) op te vragen. De basisstructuur ziet er als volgt uit:

var resultaat = from <element> in <bron>
                where <voorwaarde>
                select <element>;

Dit bestaat uit:

  • from Bepaalt de bron en de naam van het element (bijv. n in numbers).
  • where Filtert de data op basis van een voorwaarde.
  • select Geeft aan wat je als resultaat wilt krijgen.

Codevoorbeeld

Laten we een lijst van getallen nemen en alleen de even getallen selecteren.

int[] numbers = { 1, 2, 3, 4, 5, 6 };
 
// LINQ Query Syntax
var evenNumbers = from n in numbers
                  where n % 2 == 0
                  select n;

Uitleg codevoorbeeld

  1. from n in numbers → Loop door elk element n in de lijst numbers.
  2. where n % 2 == 0 → Houd alleen de even getallen over.
  3. select n → Selecteer de overgebleven waarden als eindresultaat.

Wanneer je dit uitvoert, bevat evenNumbers de waarden { 2, 4, 6 }.

Casus Declaratief vs. Imperatief Programmeren

Bij het ontwikkelen van een applicatie komt een programmeur voor de keuze tussen twee programmeerstijlen: declaratief en imperatief. Deze keuze heeft invloed op de leesbaarheid, onderhoudbaarheid en efficiëntie van de code.

De situatie
Een ontwikkelaar krijgt de taak om alle even getallen uit een lijst te filteren. Dit kan op twee manieren:

  1. Declaratieve aanpak
    De programmeur schrijft een query die beschrijft wat er moet gebeuren, zonder de details van de uitvoering te specificeren:
var evenNumbers = from n in numbers
                  where n % 2 == 0
                  select n;

Hier wordt simpelweg aangegeven: “Selecteer alle even getallen uit de lijst.” Hoe dit precies gebeurt, wordt overgelaten aan de LINQ-engine van C#.

  1. Imperatieve aanpak
    De programmeur kiest een meer stapsgewijze benadering en bepaalt zelf hoe de taak uitgevoerd moet worden:
List<int> evenNumbers = new List<int>();  
foreach (var n in numbers)  
{  
    if (n % 2 == 0)  
    {  
        evenNumbers.Add(n);  
    }  
}

Hier wordt elke stap handmatig gedefinieerd:

  • Een lege lijst aanmaken.
  • Door elk getal in de lijst itereren.
  • Controleren of het even is.
  • Het getal toevoegen aan de nieuwe lijst.

Analyse
De declaratieve aanpak is korter en leesbaarder, terwijl de imperatieve aanpak meer controle biedt, maar omslachtiger is. In moderne softwareontwikkeling wordt vaak de declaratieve stijl geprefereerd vanwege de eenvoud en efficiëntie.

Welke aanpak zou jij kiezen voor je volgende project?

Hoe gebruik je LINQ query syntax?

Je kunt LINQ query syntax goed gebruiken als:

  • je SQL-achtige leesbare query wilt schrijven.
  • je te maken hebt met complexe bevragingen zoals group by of join.
  • je samenwerkt met databases (bijv. Entity Framework).

Sorteren met orderby

LINQ Query Syntax kan ook data sorteren met orderby.

var sortedNumbers = from n in numbers
                    orderby n descending
                    select n;

Hiermee sorteer je numbers aflopend. Zonder descending zou het oplopend sorteren.

Codevoorbeeld

var numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
 
var evenNumbers = from num in numbers
                  where num % 2 == 0
                  orderby num descending
                  select num;
 
foreach (var n in evenNumbers)
{
    Console.WriteLine(n); // Output: 2, 4, 6
}

Groeperen met group by in LINQ Query Syntax

Met group by kun je gegevens groeperen op basis van een bepaalde eigenschap, net zoals in SQL. De algemene structuur is:

var resultaat = from <element> in <bron>
                group <element> by <kenmerk> into <groepsnaam>
                select <groepsnaam>;

Codevoorbeeld: Groeperen van namen op basis van hun eerste letter

string[] namen = { "Anna", "Arjen", "Bart", "Bram", "Cindy" };
 
var groepen = from naam in namen
              group naam by naam[0] into naamGroep
              select naamGroep;

Uitleg codevoorbeeld

  • group naam by naam[0] → groepeert de namen op de eerste letter.
  • into naamGroep → geeft de groep een naam.
  • select naamGroep → retourneert de groepen.

Uitvoer:

  • Groep ‘A’: { “Anna”, “Arjen” }
  • Groep ‘B’: { “Bart”, “Bram” }
  • Groep ‘C’: { “Cindy” }

Joinen van lijsten met join in LINQ Query Syntax

Met join kun je gegevens uit twee verzamelingen combineren op basis van een gemeenschappelijke eigenschap. Dit werkt zoals een INNER JOIN in SQL.

var resultaat = from <element1> in <bron1>
                join <element2> in <bron2> on <element1.eigenschap> equals <element2.eigenschap>
                select <gecombineerdResultaat>;

Codevoorbeeld Orders koppelen aan klanten

var klanten = new[]
{
    new { Id = 1, Naam = "Alice" },
    new { Id = 2, Naam = "Bob" }
};
 
var orders = new[]
{
    new { KlantId = 1, Product = "Laptop" },
    new { KlantId = 2, Product = "Telefoon" }
};
 
var klantOrders = from k in klanten
                  join o in orders on k.Id equals o.KlantId
                  select new { k.Naam, o.Product };

Uitleg Codevoorbeeld

  • from k in klanten → Selecteert alle klanten.
  • join o in orders on k.Id equals o.KlantId → Combineert klanten met hun bestellingen.
  • select new { k.Naam, o.Product } → Haalt de relevante gegevens op.

Anoniem object
Opvallend is het gebruik van het keyword new zonder klasse. Dit is een anoniem object. Dit wordt veel gebruikt bij LINQ.

Uitvoer:

  • Alice → Laptop
  • Bob → Telefoon

Left Join en Multiple Joins in LINQ Query Syntax

Een left join zorgt ervoor dat alle elementen uit de linker verzameling behouden blijven, zelfs als er geen overeenkomstige elementen in de rechter verzameling zijn.

Bij multiple joins koppel je gegevens uit meerdere verzamelingen. Dit kan handig zijn bij complexe relaties, zoals een koppeling tussen klanten, orders en producten.

Left Join in LINQ Query Syntax

C# ondersteunt geen left join direct in query syntax zoals in SQL. Maar je kunt dit simuleren met DefaultIfEmpty(), waardoor ontbrekende waarden worden opgevuld met null.

Codevoorbeeld Klanten en hun bestellingen (met klanten zonder orders)

var klanten = new[]
{
    new { Id = 1, Naam = "Alice" },
    new { Id = 2, Naam = "Bob" },
    new { Id = 3, Naam = "Charlie" } // Heeft geen order
};
 
var orders = new[]
{
    new { KlantId = 1, Product = "Laptop" },
    new { KlantId = 2, Product = "Telefoon" }
};
 
var klantOrders = from k in klanten
                  join o in orders on k.Id equals o.KlantId into klantGroep
                  from order in klantGroep.DefaultIfEmpty() // Left Join simulatie
                  select new { k.Naam, Product = order?.Product ?? "Geen bestelling" };
 
foreach (var item in klantOrders)
{
    Console.WriteLine($"{item.Naam} - {item.Product}");
}

Uitleg codevoorbeeld

  • join o in orders on k.Id equals o.KlantId into klantGroep Groepeert orders per klant.
  • from order in klantGroep.DefaultIfEmpty() Zorgt ervoor dat klanten zonder orders ook worden opgenomen (met null als er geen order is).
  • order?.Product ?? "Geen bestelling" Vervangt null door "Geen bestelling".

Uitvoer:

Alice - Laptop  
Bob - Telefoon  
Charlie - Geen bestelling  

Multiple Joins in LINQ Query Syntax

Met multiple joins kun je gegevens uit meerdere tabellen combineren.

Codevoorbeeld: Klanten, Orders en Producten

var klanten = new[]
{
    new { Id = 1, Naam = "Alice" },
    new { Id = 2, Naam = "Bob" }
};
 
var orders = new[]
{
    new { KlantId = 1, OrderId = 101 },
    new { KlantId = 2, OrderId = 102 }
};
 
var producten = new[]
{
    new { OrderId = 101, Product = "Laptop" },
    new { OrderId = 102, Product = "Telefoon" }
};
 
var klantOrders = from k in klanten
                  join o in orders on k.Id equals o.KlantId
                  join p in producten on o.OrderId equals p.OrderId
                  select new { k.Naam, p.Product };
 
foreach (var item in klantOrders)
{
    Console.WriteLine($"{item.Naam} - {item.Product}");
}

Uitleg codevoorbeeld

  • join o in orders on k.Id equals o.KlantId Koppelt klanten aan orders.
  • join p in producten on o.OrderId equals p.OrderId Koppelt orders aan producten.
  • select new { k.Naam, p.Product } Haalt de relevante gegevens op.

Uitvoer:

Alice - Laptop  
Bob - Telefoon  

Volgende stap: Oefeningen LINQ query syntax