Skip to content

ICT-Academie/SQL-Fullstack

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

8 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ—„οΈ BitByBit – SQL & .NET Core Course (v9)

Beschrijving

πŸ“„ Reader: SQL (Jaar 1)


Welkom bij de BitByBit leerlijn

In deze module leer je stap voor stap werken met SQL en databases.
Je leert hoe je data kunt ophalen, filteren, sorteren, combineren en analyseren.

Daarna koppel je de database aan .NET Core en voer je dezelfde queries uit in C# met Entity Framework (ORM).


Wat betekent dit concreet?

  • Je leert SQL queries schrijven
  • Je leert werken met een echte database
  • Je leert tabellen en relaties begrijpen
  • Je leert data analyseren
  • Je leert dezelfde logica toepassen in SQL en in C#

Waarom is dit nuttig?

Databases vormen de basis van veel informatiesystemen.
Als je begrijpt hoe data wordt opgeslagen, gekoppeld en opgevraagd, begrijp je ook beter hoe administratiesystemen, webapplicaties en backend software werken.


Wat kun je hier later mee?

  • Voorbereiding op stages en projecten
  • Sterke basis voor backend ontwikkeling
  • Inzicht in datamodellen en informatiestromen
  • Betere voorbereiding op ORM en API-ontwikkeling

🧭 Navigatie

πŸ”Ή Week 1 – Intro Database & SELECT
πŸ”Ή Week 2 – WHERE & Filtering
πŸ”Ή Week 3 – ORDER BY & DISTINCT
πŸ”Ή Week 4 – Joins & Relaties
πŸ”Ή Week 5 – GROUP BY & Aggregaties
πŸ”Ή Week 6 – Database Begrijpen
πŸ”Ή Week 7 – EF Core Scaffolding
πŸ”Ή Week 8 – SQL vs LINQ & Eindopdracht


Week 1 – Intro Database & SELECT

πŸ“Ί LessonUp
(toevoegen)

🎯 Focus

  • Wat is een database
  • Tabellen en kolommen herkennen
  • select en from
  • Data ophalen uit één tabel

πŸ§ͺ Praktijk

  • Eerste queries uitvoeren in phpMyAdmin
  • Resultaten lezen en controleren
  • Verschil zien tussen alle kolommen en een selectie van kolommen

πŸ“„ Aanvullende Lesnotities / Opdrachten

Hieronder vind je het uitgebreide weekbestand dat extra uitleg en opdrachten bevat.

Wat ga je leren

In deze week leer je hoe je gegevens uit een tabel ophaalt.
Je gebruikt hiervoor het SQL-commando select.
Met select bepaal je welke kolommen je wilt zien.
Met from geef je aan uit welke tabel de data moet komen.

Theorie

Een eenvoudige query ziet er zo uit:

select *
from klanten;

Met * vraag je alle kolommen op uit de tabel.

Je kunt ook alleen bepaalde kolommen tonen:

select naam, plaats
from klanten;

Dan zie je alleen de kolommen naam en plaats.

Opdrachten

🟒 Beginner

  1. Toon alle gegevens van alle klanten.
select *
from klanten;
  1. Toon alleen de naam en plaats van alle klanten.
select naam, plaats
from klanten;
  1. Toon alle gegevens van alle producten.
select *
from producten;
  1. Toon de omschrijving en prijs van alle producten.
select omschrijving, prijs
from producten;

🟑 Intermediate

  1. Toon de naam, plaats en het telefoonnummer van alle klanten.
select naam, plaats, telnr
from klanten;
  1. Toon de klantnaam en woonplaats met aliassen.
select naam as klantnaam, plaats as woonplaats
from klanten;
  1. Toon alle producten met een berekende prijs inclusief 21% btw.
select omschrijving, prijs, prijs * 1.21 as prijs_incl_btw
from producten;

🟠 Advanced

  1. Toon een samengestelde weergave van klanten in één kolom.
select concat(naam, ' - ', plaats) as klant_weergave
from klanten;
  1. Geef per klant aan of deze lokaal of extern is op basis van plaats.
select naam,
       case
           when plaats = 'Haarlem' then 'Lokaal'
           else 'Extern'
       end as type_klant
from klanten;
  1. Toon unieke combinaties van plaats en postcode.
select distinct plaats, postcode
from klanten;

Advies voor deze week

  • Controleer altijd eerst uit welke tabel je gegevens wilt halen.
  • Begin met select * als je nog niet precies weet welke kolommen je nodig hebt.
  • Schrijf kolomnamen nauwkeurig over om fouten te voorkomen.

πŸ” Terug naar navigatie


Week 2 – WHERE & Filtering

πŸ“Ί LessonUp
(toevoegen)

🎯 Focus

  • where
  • Vergelijkingen met =, >, <, <>, >=, <=
  • like
  • between

πŸ§ͺ Praktijk

  • Data filteren op basis van voorwaarden
  • Resultaten verkleinen zodat alleen relevante data overblijft
  • Verschil zien tussen numerieke filters en tekstfilters

πŸ“„ Aanvullende Lesnotities / Opdrachten

Hieronder vind je het uitgebreide weekbestand dat extra uitleg en opdrachten bevat.

Wat ga je leren

In deze week leer je hoe je niet alles toont, maar alleen de rijen die voldoen aan een voorwaarde.
Daarvoor gebruik je where.
Met where kun je bijvoorbeeld klanten uit één plaats tonen of producten boven een bepaalde prijs.

Theorie

Een filter op tekst ziet er zo uit:

select *
from klanten
where plaats = 'Haarlem';

Een filter op een getal ziet er zo uit:

select *
from producten
where prijs > 500;

Je kunt ook zoeken op een bereik:

select *
from producten
where prijs between 100 and 500;

Opdrachten

🟒 Beginner

  1. Toon alle klanten uit Haarlem.
select *
from klanten
where plaats = 'Haarlem';
  1. Toon alle producten met een prijs groter dan 500.
select *
from producten
where prijs > 500;
  1. Toon alle producten met een voorraad kleiner dan 10.
select *
from producten
where voorraad < 10;
  1. Toon alle klanten die niet uit Haarlem komen.
select *
from klanten
where plaats <> 'Haarlem';

🟑 Intermediate

  1. Toon alle producten met een prijs groter dan 100 Γ©n een voorraad groter dan 10.
select *
from producten
where prijs > 100
  and voorraad > 10;
  1. Toon alle klanten uit Haarlem of Amsterdam.
select *
from klanten
where plaats = 'Haarlem'
   or plaats = 'Amsterdam';
  1. Toon alle klanten waarvan de naam ergens de letter a bevat.
select *
from klanten
where naam like '%a%';

🟠 Advanced

  1. Toon alle producten die duurder zijn dan de gemiddelde prijs van alle producten.
select *
from producten
where prijs > (
    select avg(prijs)
    from producten
);
  1. Toon alle klanten die minstens één verkooporder hebben geplaatst.
select *
from klanten
where klantnr in (
    select klantnr
    from verkooporders
);
  1. Toon alle klanten die nog geen verkooporder hebben geplaatst.
select *
from klanten
where not exists (
    select 1
    from verkooporders v
    where v.klantnr = klanten.klantnr
);

Advies voor deze week

  • Zet tekst altijd tussen enkele quotes.
  • Controleer of je filter op een getal of op tekst werkt.
  • Lees je query hardop terug: β€œtoon alle … waar …”.

πŸ” Terug naar navigatie


Week 3 – ORDER BY & DISTINCT

πŸ“Ί LessonUp
(toevoegen)

🎯 Focus

  • Sorteren met order by
  • Oplopend en aflopend sorteren
  • Dubbele waarden verwijderen met distinct

πŸ§ͺ Praktijk

  • Resultaten overzichtelijk ordenen
  • Unieke waarden herkennen
  • Verschil zien tussen volledige lijsten en unieke waarden

πŸ“„ Aanvullende Lesnotities / Opdrachten

Hieronder vind je het uitgebreide weekbestand dat extra uitleg en opdrachten bevat.

Wat ga je leren

In deze week leer je hoe je resultaten sorteert.
Je gebruikt hiervoor order by.
Daarnaast leer je hoe je dubbele waarden uit een resultaat haalt met distinct.

Theorie

Sorteren op naam:

select *
from klanten
order by naam;

Aflopend sorteren op prijs:

select *
from producten
order by prijs desc;

Unieke plaatsen tonen:

select distinct plaats
from klanten;

Opdrachten

🟒 Beginner

  1. Sorteer alle klanten op naam.
select *
from klanten
order by naam;
  1. Sorteer alle producten op prijs van hoog naar laag.
select *
from producten
order by prijs desc;
  1. Toon alle unieke plaatsen van klanten.
select distinct plaats
from klanten;
  1. Sorteer alle producten op voorraad.
select *
from producten
order by voorraad;

🟑 Intermediate

  1. Sorteer klanten eerst op plaats en daarna op naam.
select *
from klanten
order by plaats, naam;
  1. Toon producten met een berekende prijs inclusief btw en sorteer daarop aflopend.
select omschrijving, prijs, prijs * 1.21 as prijs_incl
from producten
order by prijs_incl desc;
  1. Toon unieke plaatsen en sorteer die alfabetisch.
select distinct plaats
from klanten
order by plaats;

🟠 Advanced

  1. Toon de vijf duurste producten.
select *
from producten
order by prijs desc
limit 5;
  1. Sorteer klantnamen op lengte van de naam.
select naam
from klanten
order by length(naam);
  1. Sorteer producten op de waarde prijs * voorraad van hoog naar laag.
select *
from producten
order by (prijs * voorraad) desc;

Advies voor deze week

  • Gebruik asc als je expliciet oplopend wilt aangeven.
  • Gebruik desc als je aflopend wilt sorteren.
  • Vraag jezelf bij distinct af: wil ik unieke rijen of unieke waarden in één kolom?

πŸ” Terug naar navigatie


Week 4 – Joins & Relaties

πŸ“Ί LessonUp
(toevoegen)

🎯 Focus

  • Tabellen koppelen met join
  • inner join
  • left join
  • Relaties volgen tussen tabellen

πŸ§ͺ Praktijk

  • Data uit meerdere tabellen combineren
  • Klanten koppelen aan orders
  • Orders koppelen aan facturen
  • Facturen koppelen aan betalingen

πŸ“„ Aanvullende Lesnotities / Opdrachten

Hieronder vind je het uitgebreide weekbestand dat extra uitleg en opdrachten bevat.

Wat ga je leren

In deze week leer je hoe je gegevens uit meerdere tabellen combineert.
Dat doe je met een join.
Een join gebruikt de relatie tussen tabellen, bijvoorbeeld een klantnummer of ordernummer.

Theorie

Een inner join tussen klanten en verkooporders:

select k.naam, v.ordernr
from klanten k
join verkooporders v on v.klantnr = k.klantnr;

Een left join laat alle rijen van de linkertabel zien, ook als er geen match is in de rechtertabel.

select f.factuurnr, b.bedrag
from facturen f
left join betalingen b on b.factuurnr = f.factuurnr;

Opdrachten

🟒 Beginner

  1. Toon de klantnaam met het ordernummer van elke verkooporder.
select k.naam, v.ordernr
from klanten k
join verkooporders v on v.klantnr = k.klantnr;
  1. Toon het ordernummer met het factuurnummer van elke factuur.
select v.ordernr, f.factuurnr
from verkooporders v
join facturen f on f.ordernr = v.ordernr;
  1. Toon het factuurnummer met het betaalde bedrag.
select f.factuurnr, b.bedrag
from facturen f
left join betalingen b on b.factuurnr = f.factuurnr;
  1. Toon het ordernummer met de naam van de klant.
select v.ordernr, k.naam
from verkooporders v
join klanten k on k.klantnr = v.klantnr;

🟑 Intermediate

  1. Toon de naam van de klant met het factuurnummer.
select k.naam, f.factuurnr
from klanten k
join verkooporders v on v.klantnr = k.klantnr
join facturen f on f.ordernr = v.ordernr;
  1. Toon per klant het totale factuurbedrag.
select k.naam, sum(f.bedrag) as totaal_factuurbedrag
from klanten k
join verkooporders v on v.klantnr = k.klantnr
join facturen f on f.ordernr = v.ordernr
group by k.naam;
  1. Toon per klant het aantal verkooporders, ook als dat 0 is.
select k.naam, count(v.ordernr) as aantal_orders
from klanten k
left join verkooporders v on v.klantnr = k.klantnr
group by k.naam;

🟠 Advanced

  1. Toon alle klanten die nog geen verkooporder hebben.
select k.naam
from klanten k
left join verkooporders v on v.klantnr = k.klantnr
where v.ordernr is null;
  1. Toon alle facturen waarvoor nog geen betaling bestaat.
select f.factuurnr
from facturen f
left join betalingen b on b.factuurnr = f.factuurnr
where b.betalingnr is null;
  1. Toon alle klanten waarvan het totaal betaalde bedrag groter is dan 1000.
select k.naam, sum(b.bedrag) as totaal_betaald
from klanten k
join betalingen b on b.klantnr = k.klantnr
group by k.naam
having sum(b.bedrag) > 1000;

Advies voor deze week

  • Kijk altijd eerst welke kolommen de tabellen aan elkaar koppelen.
  • Gebruik aliassen zoals k, v, f en b om je query leesbaar te houden.
  • Teken desnoods eerst de relatie op papier voordat je een join schrijft.

πŸ” Terug naar navigatie


Week 5 – GROUP BY & Aggregaties

πŸ“Ί LessonUp
(toevoegen)

🎯 Focus

  • count, sum, avg, max
  • group by
  • having

πŸ§ͺ Praktijk

  • Samenvattingen maken van data
  • Tellingen en totalen berekenen
  • Verschil zien tussen where en having

πŸ“„ Aanvullende Lesnotities / Opdrachten

Hieronder vind je het uitgebreide weekbestand dat extra uitleg en opdrachten bevat.

Wat ga je leren

In deze week leer je hoe je gegevens samenvat.
Je gebruikt functies zoals count en sum.
Met group by groepeer je data.
Met having filter je groepen nadat de samenvatting is gemaakt.

Theorie

Aantal orders per klant:

select klantnr, count(*) as aantal_orders
from verkooporders
group by klantnr;

Totaal orderbedrag per klant:

select klantnr, sum(orderbedrag) as totaal
from verkooporders
group by klantnr;

Opdrachten

🟒 Beginner

  1. Tel het aantal orders per klant.
select klantnr, count(*) as aantal_orders
from verkooporders
group by klantnr;
  1. Bereken het totale orderbedrag per klant.
select klantnr, sum(orderbedrag) as totaal
from verkooporders
group by klantnr;
  1. Bereken de gemiddelde prijs van alle producten.
select avg(prijs) as gemiddelde_prijs
from producten;
  1. Zoek de hoogste productprijs.
select max(prijs) as hoogste_prijs
from producten;

🟑 Intermediate

  1. Toon alleen klanten met een totaal orderbedrag groter dan 1000.
select klantnr, sum(orderbedrag) as totaal
from verkooporders
group by klantnr
having sum(orderbedrag) > 1000;
  1. Tel hoeveel producten er per productsoort zijn.
select productsoort, count(*) as aantal_producten
from producten
group by productsoort;
  1. Zoek per klant het hoogste orderbedrag.
select klantnr, max(orderbedrag) as hoogste_order
from verkooporders
group by klantnr;

🟠 Advanced

  1. Toon per klantnaam het totale factuurbedrag.
select k.naam, sum(f.bedrag) as totaal_factuurbedrag
from klanten k
join verkooporders v on v.klantnr = k.klantnr
join facturen f on f.ordernr = v.ordernr
group by k.naam;
  1. Toon alleen klanten met meer dan één order en hun totale orderbedrag.
select klantnr, sum(orderbedrag) as totaal
from verkooporders
group by klantnr
having count(*) > 1;
  1. Toon klanten op volgorde van hoogste totale orderbedrag.
select klantnr, sum(orderbedrag) as totaal
from verkooporders
group by klantnr
order by sum(orderbedrag) desc;

Advies voor deze week

  • Gebruik where voor het filteren van losse rijen.
  • Gebruik having voor het filteren van gegroepeerde resultaten.
  • Geef berekende kolommen een alias zoals totaal of aantal_orders.

πŸ” Terug naar navigatie


Week 6 – Database Begrijpen

πŸ“Ί LessonUp
(toevoegen)

🎯 Focus

  • Primary keys
  • Foreign keys
  • Relaties tussen tabellen
  • Datamodel begrijpen voordat je code schrijft

πŸ§ͺ Praktijk

  • De structuur van de BitByBit database analyseren
  • Primary keys en foreign keys herkennen
  • Uitleggen hoe informatie door de database loopt

πŸ“„ Aanvullende Lesnotities / Opdrachten

Hieronder vind je het uitgebreide weekbestand dat extra uitleg en opdrachten bevat.

Wat ga je leren

In deze week ga je niet opnieuw een losse mini-database bouwen, maar juist de bestaande database beter begrijpen.
Dat is belangrijk, omdat je in de eerdere weken al hebt gefilterd, gesorteerd en gejoind op tabellen uit de bestaande BitByBit database.
Om goede SQL-queries te kunnen schrijven, moet je niet alleen de syntax kennen, maar ook weten hoe de tabellen inhoudelijk met elkaar verbonden zijn.
Daarom staat deze week in het teken van analyseren, herkennen en uitleggen.

Een database bestaat uit meerdere tabellen. Elke tabel heeft een eigen functie. De tabel klanten bevat bijvoorbeeld gegevens van klanten, terwijl verkooporders de geplaatste orders bevat. De tabel facturen bevat de facturen die bij orders horen en betalingen bevat de geregistreerde betalingen. Deze tabellen staan niet los van elkaar. Ze zijn met elkaar verbonden via sleutels.

De belangrijkste sleutel is de primary key. Een primary key is een kolom die elke rij in een tabel uniek maakt. In de tabel klanten is dat bijvoorbeeld klantnr. In verkooporders is dat ordernr. Door deze unieke sleutels kan de database precies weten welke rij bedoeld wordt. Zonder primary keys zou de database geen betrouwbare manier hebben om records uit elkaar te houden.

Daarnaast zijn er foreign keys. Een foreign key is een kolom die verwijst naar een primary key in een andere tabel. Zo verwijst verkooporders.klantnr naar klanten.klantnr. Dat betekent dat elke order gekoppeld is aan precies één klant. Op dezelfde manier verwijst facturen.ordernr naar verkooporders.ordernr, en verwijst betalingen.factuurnr naar facturen.factuurnr. Hierdoor ontstaat een keten van informatie: van klant naar order, van order naar factuur, en van factuur naar betaling.

Als je deze structuur begrijpt, snap je ook beter waarom joins werken. Een join is namelijk niets anders dan het combineren van tabellen op basis van zo’n relatie. Wanneer je bijvoorbeeld klantnamen met ordernummers combineert, gebruik je de relatie tussen klanten en verkooporders. Wanneer je openstaande bedragen wilt berekenen, moet je begrijpen hoe orders, facturen en betalingen samenhangen. Deze denkwijze is later ook belangrijk bij ORM en Entity Framework, omdat EF Core dezelfde relaties vertaalt naar classes en navigatie-eigenschappen in C#.

Opdrachten

🟒 Beginner

  1. Zoek in de tabel klanten welke kolom de primary key is en noteer deze.

  2. Zoek in de tabel verkooporders welke kolom de primary key is en noteer deze.

  3. Zoek in de tabel facturen welke kolom de primary key is en noteer deze.

  4. Zoek in de tabel betalingen welke kolom de primary key is en noteer deze.

🟑 Intermediate

  1. Noteer welke kolom in verkooporders verwijst naar klanten.

  2. Noteer welke kolom in facturen verwijst naar verkooporders.

  3. Noteer welke kolom in betalingen verwijst naar facturen.

  4. Schrijf in je eigen woorden op wat het verschil is tussen een primary key en een foreign key.

🟠 Advanced

  1. Schrijf de volledige relatie-keten van klant naar betaling uit in één zin.

  2. Leg uit waarom een join tussen klanten en facturen niet direct kan zonder eerst via verkooporders te gaan.

  3. Teken op papier of digitaal een eenvoudig schema van de tabellen klanten, verkooporders, facturen en betalingen.

  4. Bekijk onderstaande query en leg uit welke relaties hierin gebruikt worden.

select k.naam, f.factuurnr, b.bedrag
from klanten k
join verkooporders v on v.klantnr = k.klantnr
join facturen f on f.ordernr = v.ordernr
left join betalingen b on b.factuurnr = f.factuurnr;

Advies voor deze week

  • Kijk goed naar kolommen die op nr eindigen; dat zijn vaak sleutels.
  • Denk niet alleen in tabellen, maar in relaties tussen tabellen.
  • Als je een query lastig vindt, teken dan eerst de route van de data uit.

πŸ” Terug naar navigatie


Week 7 – EF Core Scaffolding

πŸ“Ί LessonUp
(toevoegen)

🎯 Focus

  • Database koppelen aan .NET
  • Scaffolden van classes
  • DbContext
  • Eerste data ophalen in C#

πŸ§ͺ Praktijk

  • Database omzetten naar C# classes
  • Eerste queries uitvoeren met Entity Framework Core
  • Herkennen van tabellen, properties en relaties in code

πŸ“„ Aanvullende Lesnotities / Opdrachten

Hieronder vind je het uitgebreide weekbestand dat extra uitleg en opdrachten bevat.

Wat ga je leren

In deze week ga je de bestaande database koppelen aan een .NET project.
Daarvoor gebruik je Entity Framework Core Database First.
Met scaffolding laat je EF Core classes genereren op basis van de tabellen uit de database.

Theorie

Met het volgende commando installeer je EntityFramework

dotnet tool install --global dotnet-ef

Met het volgende commando genereer je een DbContext en de modelclasses:

dotnet ef dbcontext scaffold "Server=localhost;Port=3306;Database=bitbybit;User=root;Password=;" Pomelo.EntityFrameworkCore.MySql --project BitByBit.Data --output-dir Models --context-dir Context --context BitByBitDbContext --data-annotations --no-onconfiguring --no-pluralize --force

Na het scaffolden kun je de data in C# ophalen, bijvoorbeeld:

var klanten = _db.Klanten.ToList();

Uitleg AssignmentController

In deze opdracht werken we met een API-controller in ASP.NET Core. Deze controller haalt gegevens op uit de database en stuurt deze terug als JSON.

Code

using BitByBit.Api.Dtos.Klanten;
using BitByBit.Api.Dtos.Orders;
using BitByBit.Data.Context;
using BitByBit.Data.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Globalization;

namespace BitByBit.Api.Controllers
{
    [ApiController]
    [Route("api/opdrachten")]
    public class AssignmentController : Controller
    {
        private readonly BitByBitDbContext _db;

        public AssignmentController(BitByBitDbContext db)
        {
            _db = db;
        }

        // GET: api/opdrachten/opdracht1
        [HttpGet("opdracht1")]
        public async Task<IActionResult> GetOpdracht1()
        {
            var klanten = await _db.Klanten.ToListAsync();
            return Ok(klanten);
        }
    }
}

Wat betekenen de using-statements?

Bovenaan het bestand staan verschillende using statements.

using BitByBit.Data.Context;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

Met een using geef je aan welke namespaces beschikbaar zijn binnen dit bestand.

Enkele voorbeelden:

  • BitByBit.Data.Context bevat de databasecontext.
  • Microsoft.AspNetCore.Mvc bevat onderdelen voor API-controllers.
  • Microsoft.EntityFrameworkCore bevat Entity Framework Core-functionaliteit zoals ToListAsync().

Wat is een namespace?

namespace BitByBit.Api.Controllers

Een namespace is een logische indeling van code.

Hiermee groepeer je klassen die bij elkaar horen.

In dit geval bevindt de controller zich binnen:

BitByBit.Api.Controllers

Wat is een controller?

public class AssignmentController : Controller

Een controller verwerkt HTTP-verzoeken die binnenkomen vanuit een browser, mobiele app of frontend.

Wanneer een gebruiker een URL bezoekt die bij deze controller hoort, wordt een method uitgevoerd die een antwoord terugstuurt.


Wat doet [ApiController]?

[ApiController]

Dit attribuut geeft aan dat deze klasse een API-controller is.

ASP.NET Core voegt hierdoor automatisch extra API-functionaliteit toe, zoals:

  • JSON-verwerking
  • Modelvalidatie
  • Foutafhandeling

Wat doet [Route("api/opdrachten")]?

[Route("api/opdrachten")]

Dit bepaalt het basisadres van de controller.

Alle endpoints binnen deze controller beginnen met:

/api/opdrachten

Wat is een DbContext?

private readonly BitByBitDbContext _db;

De BitByBitDbContext vormt de verbinding tussen de applicatie en de database.

Via deze context kun je tabellen benaderen.

Voorbeeld:

_db.Klanten

Hiermee wordt de tabel of entity Klanten benaderd.


Wat betekent private readonly?

private readonly BitByBitDbContext _db;

private

De variabele kan alleen binnen deze controller gebruikt worden.

readonly

De waarde mag slechts één keer worden ingesteld, namelijk in de constructor.


Wat doet de constructor?

public AssignmentController(BitByBitDbContext db)
{
    _db = db;
}

De constructor wordt uitgevoerd wanneer ASP.NET Core een nieuwe controller aanmaakt.

De databasecontext wordt automatisch aangeleverd via Dependency Injection.

Vervolgens wordt deze opgeslagen in:

_db

zodat alle methods de database kunnen gebruiken.


Wat doet [HttpGet("opdracht1")]?

[HttpGet("opdracht1")]

Dit attribuut koppelt een URL aan een method.

De onderstaande method wordt uitgevoerd wanneer een GET-request binnenkomt op:

/api/opdrachten/opdracht1

Wat betekent async?

public async Task<IActionResult> GetOpdracht1()

Het sleutelwoord async geeft aan dat deze method asynchrone code bevat.

Daardoor kan binnen de method het sleutelwoord await worden gebruikt.

Asynchroon werken zorgt ervoor dat de webserver efficiΓ«nter omgaat met wachttijden tijdens databaseverzoeken.


Wat betekent Task<IActionResult>?

Task<IActionResult>

Een Task vertegenwoordigt een taak die nog bezig kan zijn.

In dit geval betekent dit:

Deze method levert uiteindelijk een IActionResult op.

ASP.NET Core wacht automatisch totdat de taak volledig is uitgevoerd.


Wat doet await?

var klanten = await _db.Klanten.ToListAsync();

await wacht totdat de databasequery klaar is.

Zodra de gegevens zijn opgehaald, wordt de uitvoering van de method hervat.


Wat doet _db.Klanten?

_db.Klanten

Dit verwijst naar de tabel Klanten in de database.

Entity Framework gebruikt de gekoppelde entity om gegevens uit deze tabel op te halen.


Wat doet ToListAsync()?

_db.Klanten.ToListAsync();

Deze methode voert de query uit en zet het resultaat om naar een lijst van objecten.

Vergelijkbare SQL-query:

SELECT *
FROM klanten;

Het resultaat wordt opgeslagen in:

var klanten

Wat gebeurt er stap voor stap?

Wanneer een gebruiker de URL opent:

/api/opdrachten/opdracht1

gebeurt het volgende:

Stap 1

ASP.NET Core ontvangt een GET-request.

Stap 2

De route verwijst naar:

GetOpdracht1()

Stap 3

Entity Framework maakt een query voor de tabel Klanten.

Stap 4

De query wordt uitgevoerd op de database.

Stap 5

Alle klanten worden opgehaald.

Stap 6

De resultaten worden opgeslagen in:

var klanten

Stap 7

De gegevens worden teruggestuurd naar de gebruiker.

return Ok(klanten);

Wat doet Ok()?

return Ok(klanten);

Deze methode retourneert een succesvol HTTP-resultaat.

HTTP-statuscode:

200 OK

De inhoud van klanten wordt automatisch omgezet naar JSON.

Voorbeeld:

[
  {
    "klantnr": 1,
    "naam": "Jansen BV"
  },
  {
    "klantnr": 2,
    "naam": "De Vries BV"
  }
]

Endpoint testen

Deze endpoint kun je testen via Swagger:

https://localhost:xxxx/swagger/index.html

Of rechtstreeks via de browser:

https://localhost:xxxx/api/opdrachten/opdracht1

Samenvatting

Deze controller maakt een API-endpoint waarmee alle klanten uit de database worden opgehaald.

Belangrijke onderdelen:

  • AssignmentController β†’ verwerkt HTTP-verzoeken.
  • [Route("api/opdrachten")] β†’ basisadres van de controller.
  • [HttpGet("opdracht1")] β†’ endpoint voor een GET-request.
  • _db β†’ databasecontext.
  • _db.Klanten β†’ tabel Klanten.
  • ToListAsync() β†’ haalt alle klanten op.
  • await β†’ wacht op het resultaat van de databasequery.
  • Ok(klanten) β†’ stuurt de gegevens terug als JSON.

Opdrachten

🟒 Beginner

  1. Maak een nieuw .NET project aan.

  2. Installeer de NuGet packages voor EF Core en Pomelo MySQL.

  3. Voer het scaffold-commando uit.

  4. Open de gegenereerde DbContext en zoek de DbSet<Klanten> property.

🟑 Intermediate

  1. Zoek de gegenereerde class Klanten en noteer welke properties deze heeft.

  2. Zoek de gegenereerde class Verkooporders en noteer welke properties deze heeft.

  3. Zoek in de gegenereerde code een navigatieproperty die laat zien dat een klant meerdere verkooporders kan hebben.

  4. Schrijf C# code die alle klanten ophaalt.

var klanten = _db.Klanten.ToList();

🟠 Advanced

  1. Schrijf C# code die alleen de naam en plaats van klanten ophaalt.
var klanten = _db.Klanten
    .Select(k => new { k.Naam, k.Plaats })
    .ToList();
  1. Schrijf C# code die alle producten ophaalt met prijs groter dan 500.
var producten = _db.Producten
    .Where(p => p.Prijs > 500)
    .ToList();
  1. Schrijf C# code die alle klanten alfabetisch sorteert op naam.
var klanten = _db.Klanten
    .OrderBy(k => k.Naam)
    .ToList();
  1. Schrijf C# code die alle unieke plaatsen van klanten toont.
var plaatsen = _db.Klanten
    .Select(k => k.Plaats)
    .Distinct()
    .ToList();

Advies voor deze week

  • Bekijk de gegenereerde code rustig en vergelijk deze met de database-tabellen.
  • Let op het verschil tussen gewone properties en navigatieproperties.
  • Gebruik LINQ stap voor stap: eerst ophalen, dan filteren, dan sorteren.

πŸ” Terug naar navigatie


Week 8 – SQL vs LINQ & Eindopdracht

πŸ“Ί LessonUp
(toevoegen)

🎯 Focus

  • SQL vergelijken met LINQ
  • Select, Where, OrderBy
  • GroupBy, Sum
  • SelectMany
  • Denken in tabellen Γ©n in objecten

πŸ§ͺ Praktijk

  • Dezelfde informatievraag oplossen in SQL en in C#
  • Eenvoudige en meer complexe vergelijkingen maken
  • Relaties volgen via navigatie-eigenschappen

πŸ“„ Aanvullende Lesnotities / Opdrachten

Hieronder vind je het uitgebreide weekbestand dat extra uitleg en opdrachten bevat.

Wat ga je leren

In deze week ga je zien dat SQL en LINQ vaak dezelfde logica uitdrukken, maar op een andere manier.
SQL werkt direct op tabellen in de database.
LINQ werkt op objecten en collecties in C#.
Toch stel je in beide gevallen eigenlijk dezelfde vraag aan je data.

Met Select kies je in LINQ welke velden je wilt tonen. Dat lijkt op select in SQL.
Met Where filter je resultaten, net zoals where in SQL.
Met OrderBy sorteer je data, net zoals order by in SQL.
Als je totalen wilt berekenen, gebruik je in SQL vaak sum, en in LINQ gebruik je .Sum(...).

SelectMany is een belangrijk onderdeel wanneer je door meerdere relaties heen wilt lopen. Stel dat een klant meerdere verkooporders heeft, en dat elke verkooporder weer meerdere facturen heeft. Dan krijg je in C# eigenlijk een lijst van klanten, met daarin een lijst van orders, met daarin weer een lijst van facturen. Met SelectMany maak je van zo’n geneste structuur één platte lijst. Daardoor kun je daarna makkelijker rekenen, filteren of projecteren. Zonder SelectMany blijf je werken met een verzameling van verzamelingen, en dat maakt je query lastiger te begrijpen.

SQL en LINQ voorbeelden

Voorbeeld 1 – Alleen namen van klanten

SQL

select naam
from klanten;

LINQ

var klanten = _db.Klanten
    .Select(k => k.Naam)
    .ToList();

Voorbeeld 2 – Klanten uit Haarlem

SQL

select *
from klanten
where plaats = 'Haarlem';

LINQ

var klanten = _db.Klanten
    .Where(k => k.Plaats == "Haarlem")
    .ToList();

Voorbeeld 3 – Klanten sorteren op naam

SQL

select *
from klanten
order by naam;

LINQ

var klanten = _db.Klanten
    .OrderBy(k => k.Naam)
    .ToList();

Voorbeeld 4 – Totaal orderbedrag per klant

SQL

select klantnr, sum(orderbedrag) as totaal
from verkooporders
group by klantnr;

LINQ

var totalen = _db.Verkooporders
    .GroupBy(v => v.Klantnr)
    .Select(g => new
    {
        Klantnr = g.Key,
        Totaal = g.Sum(v => v.Orderbedrag)
    })
    .ToList();

Voorbeeld 5 – Openstaand bedrag per klant

SQL

select
    k.klantnr,
    k.naam,
    sum(f.bedrag - coalesce(b.betaald_bedrag, 0)) as openstaand_bedrag
from klanten k
inner join verkooporders v
    on v.klantnr = k.klantnr
inner join facturen f
    on f.ordernr = v.ordernr
left join (
    select factuurnr, sum(bedrag) as betaald_bedrag
    from betalingen
    group by factuurnr
) b
    on b.factuurnr = f.factuurnr
group by k.klantnr, k.naam
having sum(f.bedrag - coalesce(b.betaald_bedrag, 0)) > 0
order by k.naam;

LINQ

var klantenMetOpenstaand = _db.Klanten
    .Select(k => new
    {
        k.Klantnr,
        k.Naam,
        OpenstaandBedrag = k.Verkooporders
            .SelectMany(v => v.Facturen)
            .Sum(f => f.Bedrag - (f.Betalingen.Sum(b => (decimal?)b.Bedrag) ?? 0))
    })
    .Where(k => k.OpenstaandBedrag > 0)
    .OrderBy(k => k.Naam)
    .ToList();

Opdrachten

🟒 Beginner

  1. Schrijf de SQL-query om alle klantnamen op te halen.
select naam
from klanten;
  1. Schrijf de LINQ-query die hetzelfde doet.
var klanten = _db.Klanten
    .Select(k => k.Naam)
    .ToList();
  1. Schrijf de SQL-query om alle klanten uit Haarlem op te halen.
select *
from klanten
where plaats = 'Haarlem';
  1. Schrijf de LINQ-query die hetzelfde doet.
var klanten = _db.Klanten
    .Where(k => k.Plaats == "Haarlem")
    .ToList();

🟑 Intermediate

  1. Schrijf de SQL-query om alle klanten op naam te sorteren.
select *
from klanten
order by naam;
  1. Schrijf de LINQ-query die hetzelfde doet.
var klanten = _db.Klanten
    .OrderBy(k => k.Naam)
    .ToList();
  1. Schrijf de SQL-query om het totale orderbedrag per klantnummer te tonen.
select klantnr, sum(orderbedrag) as totaal
from verkooporders
group by klantnr;
  1. Schrijf de LINQ-query die hetzelfde doet.
var totalen = _db.Verkooporders
    .GroupBy(v => v.Klantnr)
    .Select(g => new
    {
        Klantnr = g.Key,
        Totaal = g.Sum(v => v.Orderbedrag)
    })
    .ToList();

🟠 Advanced

  1. Bestudeer de LINQ-query met SelectMany en leg in je eigen woorden uit waarom SelectMany nodig is.
var klantenMetOpenstaand = _db.Klanten
    .Select(k => new
    {
        k.Klantnr,
        k.Naam,
        OpenstaandBedrag = k.Verkooporders
            .SelectMany(v => v.Facturen)
            .Sum(f => f.Bedrag - (f.Betalingen.Sum(b => (decimal?)b.Bedrag) ?? 0))
    })
    .ToList();
  1. Schrijf de SQL-query om alleen klanten met een openstaand bedrag groter dan 0 te tonen.
select
    k.klantnr,
    k.naam,
    sum(f.bedrag - coalesce(b.betaald_bedrag, 0)) as openstaand_bedrag
from klanten k
inner join verkooporders v
    on v.klantnr = k.klantnr
inner join facturen f
    on f.ordernr = v.ordernr
left join (
    select factuurnr, sum(bedrag) as betaald_bedrag
    from betalingen
    group by factuurnr
) b
    on b.factuurnr = f.factuurnr
group by k.klantnr, k.naam
having sum(f.bedrag - coalesce(b.betaald_bedrag, 0)) > 0;
  1. Schrijf de LINQ-query die klanten met een openstaand bedrag groter dan 0 toont.
var klantenMetOpenstaand = _db.Klanten
    .Select(k => new
    {
        k.Klantnr,
        k.Naam,
        OpenstaandBedrag = k.Verkooporders
            .SelectMany(v => v.Facturen)
            .Sum(f => f.Bedrag - (f.Betalingen.Sum(b => (decimal?)b.Bedrag) ?? 0))
    })
    .Where(k => k.OpenstaandBedrag > 0)
    .ToList();
  1. Maak een eigen vergelijking tussen één SQL-query en één LINQ-query uit deze week en leg uit welke onderdelen bij elkaar horen.

Advies voor deze week

  • Denk eerst in SQL: wat wil je precies weten?
  • Vertaal daarna stap voor stap naar LINQ.
  • Vergelijk niet alleen de syntax, maar vooral de logica van de query.

πŸ” Terug naar navigatie

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors