De opvallendste veranderingen in Entity Framework Core 6.0

Blog

EF Core 6

Entity Framework Core 6 is gelijktijdig met .NET 6 gelanceerd, namelijk afgelopen november (2021). Daarmee heeft EF Core 6 net als .NET 6 Long Term Support (LTS). EF Core 6 heeft natuurlijk veel wijzigingen ten opzichte van EF Core 5. Een aantal opvallende wijzigingen neem ik door in deze blog. Ook kijk ik vooruit naar november 2022, waar EF 7.0 wordt aangekondigd. Wat kan je daarvan verwachten?

Temporal tabellen

Met Temporal tabellen kan je versies toevoegen aan een bestaande tabel. EF maakt dan een tweede tabel aan met validatiedatums voor de opgeslagen data. Deze temporal tabel kan volledig geconfigureerd worden. Uiteraard kan deze tweede tabel ook gewoon doorzocht worden. Om deze data op te halen zijn er specifieke functies binnen EF beschikbaar.

Momenteel is deze functie alleen beschikbaar binnen Microsoft databases, maar er is ook “third-party” ondersteuning voor PostgeSQL. Meer informatie over Temporal tabellen vind je hier.

Migration Bundles

Met migration bundles kan je één of meer migraties bundelen tot een executable die je kan geïmplementeerd kan worden in een CI/CD omgeving. De functie is enigszins vergelijkbaar met DbUp, al zou ik zelf toch nog eerder DbUp gebruiken dan deze functionaliteit. Bij DbUp zet je alle SQL scripts in een aparte folder en stel je deze in als embedded resource. Een tip hier is om die folder in z’n geheel te markeren als embedded resource door wildcards te gebruiken in het .csproj bestand.

Meer informatie over migration bundles vind je hier. Meer informatie over DbUp staat hier.

Pre-convention modelconfiguratie

Door in je DbContext class ConfigureConventions te overschrijven, kun je standaard modelconfiguratie toevoegen. Op basis van het type kan je standaardconfiguratie, zoals string-lengte, unicode en de precisie van decimalen bepalen voor het gehele model.

Met deze configuratie kan je ook converters toevoegen en ook properties bij voorbaat uitsluiten.

Meer informatie over pre-convention modelconfiguratie, vind je hier.

UnicodeAttribute

Met deze attribute kan je aangeven of een property Unicode is of niet. Dit kon je natuurlijk al aangeven in de Entity Type Configuratie, maar niet als attribute. Dat kan nu dus wel.

Standaard zet EF Core string properties om naar Unicode, dus deze attribute is vooral bedoeld om Unicode uit te zetten. Als een database alleen Unicode type accepteert, dan wordt het attribute genegeerd.

UnicodeAttribute is onderdeel van het NuGet-package Microsoft.EntityFrameworkCore.Abstractions.

Model building verbeteringen

Er zijn nog verschillende andere verbeteringen, waaronder betere ondersteuning van conversies, zodat je aan kan geven hoe je enums wilt opslaan. Ook is het makkelijker geworden om many-to-many koppelingen te configureren.

Wat er nog meer aan verbeteringen in EF Core zitten, vind je hier.

EF7

In november 2022 komt EF7 uit, gelijktijdig met .NET 7. Net als .NET 7 heeft deze versie geen LTS. Het is ook de eerste versie waar Core uit de naam verdwenen is; er is nu geen verwarring meer met oude versies aangezien de laatste “oude” versie ook een versie 6 had. EF7 borduurt weer verder op EF Core 6. Hoewel nog niet alle wijzigingen duidelijk zijn, is er al wel duidelijk wat er in de planning zit:

JSON-Kolommen

JSON-kolommen zijn kolommen waarin JSON-tekst wordt opgeslagen. De bedoeling is dat de JSON properties gemapt kunnen worden naar de properties in de entities.

Meer informatie over JSON kolommen vind je hier.

Bulk Updates

Een ander voorstel voor EF7 zijn “bulk updates”. Zonder data in het geheugen te laden, kunnen dan veel regels bijgewerkt worden.

Meer informatie over bulk updates vind je hier.

Grafische User Interface

Dit voorstel gaat over betere ondersteuning voor Windows Forms en .NET MAUI. Het is namelijk niet altijd eenvoudig om de technieken met elkaar te verbinden. In EF7 wordt de ervaring van in EF Core en in Visual Studio verbeterd. In de basis gaat het om het herintroduceren van Visual Studio tooling, zodat het ongeveer gelijk werkt zoals in .NET Framework.

Migratie van EF6 naar EF7

De vorige Entity Framework versie 6 - de versie van 17 oktober 2013 en dus niet te verwarren met EF Core 6 - was een vrij complete versie. In EF7 worden ontbrekende functionaliteiten uit EF6 toegevoegd. Het is op dit moment nog niet duidelijk welke functionaliteit van EF6 wordt toegevoegd aan EF7. Wel is duidelijk dat deze functionaliteit het makkelijker moet maken om de EF6 projecten te porten naar EF7.

Meer informatie

Op onze GitHub-pagina kun je de demo repository vinden. Hierin zijn wat shortcuts genomen, maar geeft wel een beeld van hoe Entity Framework werkt.

In de readme van de repository vind je meer informatie en links over EF Core 6 en EF7.

Mocht je hier nou nog vragen over hebben, of hulp van één van onze .NET Developers kunnen gebruiken… laat het ons weten! We kijken graag een keer met je mee.

Michiel
Auteur Michiel Developer

Heb je vragen over dit onderwerp of zou je Michiel willen inhuren voor een vergelijkbare opdracht?

Neem contact met ons op

Gerelateerde artikelen

Raymon Raymon / 21-03-2022

7 minuten lezen

Om te beginnen: wat is end-to-end testen? We hebben twee zogeheten ‘ends’ in een webapplicatie: de Front-End en de Back-End. Met unit-testing testen we de code voor ofwel de Front-End ofwel de Back-End. We testen niet hoe de applicatie zich gedraagt in de browser of hoe beide ends samenwerken.

Begrijp me niet verkeerd: ik ben voorstander van unit tests! Maar het is net zo belangrijk om te testen hoe de Front-End en de Back-End samenwerken.

Met end-to-end testen kijk je of de Front-End goed samenwerkt met de Back-End. Zo moet bijvoorbeeld het automatisch invullen van formulieren worden getest met een end-to-end test, maar ook het klikken op knoppen en het navigeren door de pagina’s.

Deze end-to-end tests controleren dus of de Front-End de gegevens vanuit de Back-End correct verwerkt.

Wat is Cypress?

Er zijn veel end-to-end testtoolkits, maar een van de meest populaire en snelste toolkits is Cypress.

Cypress biedt een manier om end-to-end tests te schrijven met JavaScript en de testrunner. Daarnaast biedt het de mogelijkheid om screenshots en video’s op te slaan wanneer een test mislukt. En, waar de meeste organisaties blij van worden: het is open-source. En dat is geweldig.

End-to-end testen met Cypress

In de Cypress-documentatie staat een geweldige tutorial waarin je op weg wordt geholpen bij het schrijven van end-to-end-tests.

Stap 1: configureren

Stap 1: configureren

Aan de basis van het project bevindt zich een cypress.json, waar je enkele standaardconfiguraties kunt wijzigen. In ons project ziet het er als volgt uit:

 

{
    "testFiles": "**/*.e2e.test.js",
    "chromeWebSecurity": false
}


In de property testFiles vertellen we Cypress om te zoeken naar bestanden die e2e.test.js in de naam bevatten. Je kunt Cypress configureren met TypeScript, maar in dit geval denk ik dat dat geen toegevoegde waarde heeft. Het vereist een extra transpilatie-stap die langer duurt.

Stap 2: testbestanden opslaan

Stap 2: testbestanden opslaan

Bij unit-testing is het heel gebruikelijk om de tests op te slaan in de componentmappen. In dit geval neemt Cypress de map cypress/integration als root om naar de bestanden te zoeken. We hebben dus een structuur die gebaseerd is op de applicatie zelf, waarin we de end-to-end testbestanden opslaan.

Stap 3: de test voorzien van minimale eisen

Stap 3: de test voorzien van minimale eisen

Elke test heeft ten minste een function describe() met daarin ten minste één it() function. Dit werkt op dezelfde manier als het schrijven van unit-tests:

 

describe('My First Test', () => {
  it('Does not do much!', () => {
    expect(true).to.equal(true)
  })
})


Dit voorbeeld lijkt op een unit-test. We moeten dus gebruik maken van de Cypress Library. Je kunt dat gebruiken door cy te gebruiken zoals in het onderstaande voorbeeld, waarin we https://example.cypress.io bezoeken.

 

describe('My First Test', () => {
  it('Visits the Kitchen Sink', () => {
    cy.visit('https://example.cypress.io')
  })
})


Je kunt zien dat de echte browser deze actie uitvoert door npm run e2e:open uit te voeren.

Onze scripts in de package.json zien er als volgt uit:

 

{
//...
"e2e:run": "npx cypress run --config-file cypress.json",
"e2e:open": "npx cypress open --config-file cypress.json",
"e2e:open:edge": "npx cypress open --browser edge --config-file cypress.json",
"e2e:open:firefox": "npx cypress open --browser firefox --config-file cypress.json"
//...
}


Cypress start de toepassing en daar kan je de end-to-end-test selecteren die je wilt uitvoeren. Standaard wordt de Chrome-browser geopend, maar er is ook een optie om het in Firefox of Edge uit te voeren.

Cypress biedt een complete bibliotheek en je kunt de documentatie raadplegen voor meer informatie hierover.

Stap 4: testen!

Stap 4: testen!

We zullen vooral zaken die in de browser verschijnen of veranderen testen met end-to-end tests. Een eenvoudig scenario: we bezoeken pagina x en controleren of de h1 de tekst “Dit is een geweldige titel” bevat.

 


describe('My First Test', () => {
  it('Visits the Kitchen Sink', () => {
    cy.visit('https://example.cypress.io');
    cy.get('h1').should('contain.text', ' Dit is een geweldige titel');
  })
})


In dit voorbeeld maakt elke methode die je aanroept vanuit de cy-bibliotheek deel uit van het testen. Zo zal cy.visit() de actie uitvoeren, maar als er geen geldige pagina op die URL staat, zal de test niet slagen. Dus met elke actie die je uitvoert, begin je een ‘assertion’.

In Cypress zijn er twee verschillende soorten ‘assertions’. should() of and() zijn “Implicit Subjects”. .expect is een “Explicit Subject”. Lees hier meer over in de Cypress-documentatie.

Bij het aanroepen van cy.get(‘h1’) zal het zoeken naar de H1-tag. Wanneer het dat element vindt, gaat de test verder. De test zal falen indien het element niet binnen een paar milliseconden wordt gevonden. Na de get-method kun je een heleboel andere methoden koppelen, zoals:

  • .contains() verwacht dat het element met inhoud uiteindelijk in de DOM zal bestaan.
  • .find() verwacht ook dat het element uiteindelijk in de DOM zal bestaan.
  • .type() verwacht dat het element uiteindelijk in een typbare staat zal zijn.
  • .click() verwacht dat het element zich uiteindelijk in een bruikbare staat bevindt.
  • .its() verwacht uiteindelijk een property over het huidige onderwerp te vinden.

Dus wat testen we met end-to-end-tests?

  1. Of een element een bepaalde klasse heeft (cy.get(‘element.selector’).should(‘have.class’, ‘ng-valid’); ) of juist niet (cy.get(‘element.selector’).should(‘not.have.class’, ‘ng-valid’);).
  2. Of een lijst 3 onderliggende elementen heeft ( cy.get(‘ul > li’).should(‘have.length’, 3); ).
  3. Controleren of een invoerveld of tekstgebied een bepaalde waarde heeft ( cy.get(‘input[name=“firstName”]’).type(‘Santa Claus’).should(‘have.value’, ‘Santa Claus’); ).

Bekijk deze lijst met voorbeelden van wat je kunt gebruiken in de should-method.

Extra voorbeeld:

Je kunt de context van een bovenliggend element toevoegen om assertions uit te voeren, wat handig is bij formulieren.

 

<form>
  <input name="email" type="email" />
  <input name="password" type="password" />
  <button type="submit">Login</button>
</form>

describe('My First Test', () => {
  it('Visits the Kitchen Sink', () => {
    cy.visit('https://example.cypress.io');
    cy.get('form').within(($form) => {
        // you have access to the found form via
        // the jQuery object $form if you need it

        // cy.get() will only search for elements within form,
        // not within the entire document
        cy.get('input[name="email"]').type('john.doe@email.com')
        cy.get('input[name="password"]').type('password')
        cy.root().submit()
    })
  })
})


Kijk voor meer voorbeelden van de within()-method in de Cypress-documentatie.

Herbruikbare functionaliteit

In het geval van herbruikbare acties die je keer op keer uitvoert, kan je eenvoudige functies schrijven die je in een lib-map kunt plaatsen. Maar Cypress biedt een gebruiksvriendelijkere manier om dit te doen. Dit wordt “custom commands” genoemd; hiervan kan je veel voorbeelden vinden in de documentatie.

Maar een van de beste voorbeelden is het schrijven van de command voor de login. Je moet die code toevoegen aan het bestand cypress/support/commands.js.

 

Cypress.Commands.add('login', (userType, options = {}) => {
  // this is an example of skipping your UI and logging in programmatically

  // setup some basic types
  // and user properties
  const types = {
    admin: {
      name: 'Jane Lane',
      admin: true,
    },
    user: {
      name: 'Jim Bob',
      admin: false,
    },
  }

  // grab the user
  const user = types[userType]

  // create the user first in the DB
  cy.request({
    url: '/seed/users', // assuming you've exposed a seeds route
    method: 'POST',
    body: user,
  })
    .its('body')
    .then((body) => {
      // assuming the server sends back the user details
      // including a randomly generated password
      //
      // we can now login as this newly created user
      cy.request({
        url: '/login',
        method: 'POST',
        body: {
          email: body.email,
          password: body.password,
        },
      })
    })
})


Conclusie

Nu is het aan jou om geweldige end-to-end tests te schrijven met Cypress! Perfecte tests bestaan niet, maar als je ze elke keer een beetje optimaliseert, wordt het je ‘source of truth’. De end-to-end-tests zijn geweldig voor developers om uit te voeren na het bouwen van een nieuwe functie of het wijzigen van een bestaande, omdat het onmogelijk is om alle testscenario’s te onthouden.

Veel succes en plezier met het schrijven van waardevolle end-to-end tests! Als we je hierbij kunnen helpen, doen mijn collega’s en ik dat natuurlijk graag.

/ 24-02-2022

2 minuten lezen

Hoe gaaf zou het zijn om een applicatie te draaien in een omgeving die zich continu op basis van de behoefte uitbreidt of zelfs verkleint? Een omgeving die volledig geautomatiseerd als een mechanisme functioneert en dynamisch is? De wereld van hedendaagse containers en microservices is een oplossing die dit kan waarmaken. Dit wordt mede mogelijk gemaakt door Kubernetes (in het Grieks “stuurman (iemand die aan het roer staat) of piloot”).

Traditionele datacentertechnieken waarbij elke applicatie op een afzonderlijke virtuele machine draait, vragen veel kracht en brengen zo hoge kosten met zich mee. Kubernetes daarentegen is een orchestrator die de onderliggende container-virtualisatie-software (Docker) aan het managen is. Het opspinnen of opschalen van een container duurt in veel gevallen enkele seconden, omdat het alleen een container hoeft op te spinnen in plaats van eerst een systeem met daaropvolgend de applicatie. Op het gebied van schaalbaarheid en performance zorgt deze oplossing voor een efficiënt applicatielandschap.

Kubernetes fungeert als orchestrator

Wat moet je je voorstellen bij Kubernetes?

Je kunt het eigenlijk vergelijken met een zeehaven waar de Docker Nodes de containerschepen zijn en dat Kubernetes de kranen, geautomatiseerde voertuigen en opslag van de containers in de haven beheert. Op basis van de vraag naar containers breidt Kubernetes de omgeving uit en plaatst dit zelf op de schepen (Docker Nodes). Het plaatsen van de containers wordt bepaald door de configuratie van de orchestrator.

Het is te vergelijken met een zeehaven

Een oplossing die zelfs Kubernetes automatiseert

Hoe mooi zou het zijn om zelfs Kubernetes te automatiseren? Om dit gemakkelijker te maken heeft Microsoft een mooi laagje over het hele Kubernetes platform gebouwd: AKS (Azure Kubernetes Services). AKS is een samenstelling van de Operating System, Virtualisatie Software (Docker) en Orchestrator (Kubernetes). Dit maakt deployment en management on the go mogelijk. Vanuit de Azure portal is het mogelijk om met een aantal drukken op de knop een volledige Kubernetes cluster uit te rollen.

Je vraagt je dan misschien af hoe het zit met de configuratie. Die zijn simpel in te laden door parameter files en de meest belangrijke opties zijn al aan te passen via de Web interface. Zoals het opschalen van de nodes en het verkrijgen van nuttige informatie over de workload (pods), nodes (workers), networking, security en identity and access management van de omgeving.

Dit was het even in het kort over Kubernetes. De volgende keer gaan we dieper in op verschillende onderdelen. Mochten mijn collega’s en ik je in de tussentijd kunnen helpen bij het werken met Kubernetes of een ander vraagstuk binnen Azure, laat het ons weten. We helpen graag!

{description}

Hoor van onze experts hoe leuk ShareValue is

Lees de verhalen van onze collega's
{description}

Heb je een .NET expert nodig?

Neem contact met ons op