Onze website bevat functionele en analytische cookies die nodig zijn om de website goed te laten functioneren en jou als bezoeker een goede webervaring te geven. Deze statistieken worden volledig anoniem verwerkt. Meer informatie is beschikbaar in onze privacyverklaring.
12 minuten lezen
Het internet staat tegenwoordig vol met Pixel Displays zoals de Divoom Pixoo-64 of misschien wel de bekendste, de LaMetric clock. Maar de prijzen van deze displays schrokken mij nogal af. Toen kwam ik op Amazon de Coolwell RGB Full-Color LED Matrix Panel tegen.
Toevallig had mijn collega Raymon hetzelfde scherm gevonden en al in bezit. Hij kon mij precies vertellen wat er allemaal bij zat en wat er nog moest worden aangeschaft. Met maar 40 euro is dit een veel schappelijkere prijs. Echter kan het scherm zelf niet meer dan hem verteld wordt, dus is er een controller nodig. Iets wat het scherm vertelt “dit moet je tonen”.
De Raspberry Pi zou hier zeer geschikt voor zijn, klein maar krachtig genoeg om een API te draaien en het scherm aan te sturen. Zo is dit project dus begonnen.
In deze blog leg ik de volgende dingen uit:
Kabel mapping
Om het scherm aan te sturen, moet deze worden aangesloten op de Raspberry Pi. De pins van het scherm moeten op de juiste pins van de GPIO header van de Raspberry Pi worden aangesloten zodat de Raspberry Pi de commando’s kan geven om op het scherm te tekenen.
GPIO header pins
De GPIO (General Purpose Input/Output) header pins op een Raspberry Pi zijn fysieke aansluitpunten op het bord die verschillende functies bieden voor het verbinden van externe apparaten.
Voor meer informatie over de functionaliteit van alle pins verwijs ik door naar: https://pinout.xyz/pinout/pin3_gpio2 en https://www.raspberrypi-spy.co.uk/2012/06/simple-guide-to-the-rpi-gpio-header-and-pins/
Pixel display pins
Het pixel display heeft de volgende pins op de achterkant:
Mapping
De pins die gebruikt worden voor het aansturen van het pixel display zijn:
* Dit is een algemene GPIO-pin
Scherm
Om het scherm aan te sturen heb ik gebruik gemaakt van een open-source library, ontwikkeld door Henner Zeller, voor het aansturen van RGB LED-matrixpanelen met de Raspberry Pi: https://github.com/hzeller/rpi-rgb-led-matrix
Deze library stelt je in staat om RGB LED-matrixpanelen aan te sluiten op je Raspberry Pi en ze te bedienen via de GPIO-pinnen. Het biedt geavanceerde functionaliteiten voor het weergeven van kleurrijke patronen, afbeeldingen en animaties op de LED-matrix.
Om deze library te kunnen gebruiken in een .NET project, moet er een dll van gemaakt worden. Gelukkig heeft Henner hier aan gedacht en hier een handleiding voor geschreven: https://github.com/hzeller/rpi-rgb-led-matrix/tree/master/bindings/c%23
Mapping testen
Voordat er code geschreven kan worden moet er eerst getest worden of het scherm goed werk en/of de kabels goed zijn aangesloten op de Raspberry Pi. De eerder genoemde library heeft een aantal scripts om bijvoorbeeld tekst op het scherm te printen, een plaatje te tonen of scrolling tekst.
Door deze scripts aan te roepen kon ik zien of de kabels goed zaten. Zo zaten er bij de eerste keer de B en D kabels omgedraaid, wat er in resulteerde dat de onderste helft van het plaatje boven getoond werd en andersom. Als alle scripts de juiste output tonen is het tijd om verder te gaan naar het schrijven van C# API.
.NET
Als de kabels goed zitten en de dll gemaakt is, kunnen we het .NET project opzetten. Ik heb gekozen voor een API, omdat ik het vanaf het netwerk of misschien zelfs vanaf het internet aan wil kunnen roepen. Maar uiteraard kan er ook een console application gemaakt worden om het scherm aan te sturen, dit ligt eraan wat de wensen zijn.
API
Nu de keuze duidelijk is kan ik eindelijk code gaan schrijven. Natuurlijk met de nieuwste .NET versie, en dat is op het moment van schrijven .NET 7.
De API moet een REST API zijn en vooralsnog zonder authenticatie, want eerst moet getest worden of alles werkt. De authenticatie is alleen echt nodig als het scherm echt wordt opgehangen voor gebruik, en zelfs dan kan het zelfs niet nodig zijn. Natuurlijk als het scherm aan het internet gehangen wordt, dan moet er wel authenticatie ingebouwd worden.
Plaatjes
De REST API endpoint maken was het makkelijke werk, maar hoe zet je een plaatje om naar pixels? Het scherm bestaat immers uit pixels. Dit heb ik gedaan met de volgend code:
public void DrawBitmapFromUrl(string imageUrl)
{
var bitmap = GraphicsHelper.GetBitmapFromUrl(imageUrl, _ledRows, _ledColumns).Result;
var canvas = Matrix.CreateOffscreenCanvas();
canvas = DrawBitmapOnCanvas(canvas, bitmap);
SwapCanvas(canvas);
}
Het endpoint roept DrawBitmapFromUrl aan, deze vraagt aan de GraphicsHelper om de bitmap op te halen. Vervolgens wordt er een canvas aangemaakt om op te tekenen, de bitmap wordt daarop getekend en het canvas wordt verwisseld met de huidige canvas die op het scherm getoond wordt. Het wisselen van de canvas is het daadwerkelijke tekenen op het scherm.
public static async Task<SKBitmap> GetBitmapFromUrl(string url, int screenWidth, int screenHeight)
{
using var client = new HttpClient();
using var response = await client.GetAsync(url);
using var stream = await response.Content.ReadAsStreamAsync();
var bitmap = SKBitmap.Decode(stream);
return ResizeBitmap(screenWidth, screenHeight, bitmap);
}
De GetBitmapFromUrl methode download het plaatje en zet het om naar een stream. De stream kan gedecode worden naar een SKBitmap. Deze wordt vervolgens aan de ResizeBitmap method gegeven met de hoogte en breedte van het scherm.
SKBitmap is onderdeel van de SkiaSharp Nuget package: https://www.nuget.org/packages/SkiaSharp/
private static SKBitmap ResizeBitmap(int screenWidth, int screenHeight, SKBitmap bitmap)
{
int targetWidth, targetHeight;
CalculateDimensions(bitmap, screenWidth, screenHeight, out targetWidth, out targetHeight);
// Create a new bitmap with the desired dimensions
var resizedBitmap = new SKBitmap(targetWidth, targetHeight);
// Create a new surface from the resized bitmap
using (var surface = new SKCanvas(resizedBitmap))
{
// Draw the original bitmap onto the new surface, scaling it to fit while maintaining aspect ratio
surface.DrawBitmap(bitmap, SKRect.Create(targetWidth, targetHeight));
}
return resizedBitmap;
}
De ResizeBitmap method berekend de hoogte en breedte aan de hand van de dimensies van het scherm met behoud van de aspect ratio. Vervolgens wordt er een SKCanvas geïnitialiseerd met de juiste dimensies en daar wordt de bitmap op getekend.
Gifjes
Gifjes tekenen op het scherm gaat bijna hetzelfde als een plaatje. Alleen een gifje is niet een stilstaand plaatje. Een gif bestaat uit meerdere plaatjes die een bepaalde periode getoond worden.
private RGBLedCanvas DrawGifOnCanvas(RGBLedCanvas canvas, string imageUrl, RenderPoint start, RenderPoint end, CancellationToken cancellationToken)
{
(List<SKBitmap> frames, List<int> durations) = GraphicsHelper.IsBase64String(imageUrl) ? GraphicsHelper.GetGifFromBase64(imageUrl, end.Y - start.Y, end.X - start.X) : GraphicsHelper.GetGifFromUrl(imageUrl, end.Y - start.Y, end.X - start.X);
while(!cancellationToken.IsCancellationRequested)
{
for(var i = 0; i < frames.Count; i++)
{
canvas = DrawBitmapOnCanvas(canvas, frames[i], start, end);
canvas = SwapCanvas(canvas);
Thread.Sleep(durations[i]);
}
}
return canvas;
}
De DrawGifOnCanvas methode vraag aan de GraphicsHelper om de gif op te halen en krijgt een tuple van frames en durations terug. Door deze tuple wordt heen gelopen, de bitmap wordt op het scherm getekend en vervolgens wordt er gewacht ( de duration van de bitmap ).
public static (List<SKBitmap> frames, List<int> durations) GetGifFromUrl(string url, int screenWidth, int screenHeight)
{
using var client = new HttpClient();
using var stream = client.GetAsync(url).Result.Content.ReadAsStream();
return GetGifFromStream(screenWidth, screenHeight, stream);
}
Deze methode download het gifje, geeft deze aan GetGifFromStream mee en geeft het resultaat terug.
private static (List<SKBitmap> frames, List<int> durations) GetGifFromStream(int screenWidth, int screenHeight, Stream response)
{
using (var codec = SKCodec.Create(response))
{
var frameCount = codec.FrameCount;
Console.WriteLine($"Frame count: {codec.FrameCount}");
var info = codec.Info;
var count = codec.FrameCount;
// Get all frames from gif and duration and add to list
var bitmap = new SKBitmap(info);
var frames = new List<SKBitmap>();
var frameLengths = new List<int>();
for (int i = 0; i < count; i++)
{
var opts = new SKCodecOptions(i);
if (codec?.GetPixels(info, bitmap.GetPixels(), opts) == SKCodecResult.Success)
{
bitmap.NotifyPixelsChanged();
var resized = ResizeBitmap(screenWidth, screenHeight, bitmap);
frames.Add(resized);
frameLengths.Add(codec.FrameInfo[i].Duration);
}
}
return (frames, frameLengths);
}
}
GetGifFromStream maakt een SKCodec (SkiaSharp) en loopt door de frames. Van elk frame wordt de bitmap opgehaald (geresized naar de juiste dimensies) en de duration.
Tekst
Om tekst te tonen op het scherm roept de endpoint DrawText aan.
public void DrawText(string text, CancellationToken cancellationToken)
{
text = text ?? "This is a static text.";
var canvas = Matrix.CreateOffscreenCanvas();
canvas = DrawTextOnCanvas(canvas, text, new RenderPoint(1, 6), null);
SwapCanvas(canvas);
}
De canvas is aangemaakt om op te tekenen en DrawTextOnCanvas wordt aangeroepen. Vervolgens wordt er weer de SwapCanvas methode aangeroepen om de tekst op het scherm te tekenen.
private RGBLedCanvas DrawTextOnCanvas(RGBLedCanvas canvas, string text, RenderPoint start, RenderPoint? end)
{
var font = new RGBLedFont("fonts/6x10.bdf");
var textLength = canvas.DrawText(font, start.X, start.Y, new Color(0, 255, 0), text);
// TODO make text as big as fits in the section
canvas.DrawText(font, start.X, start.Y, new Color(0, 255, 0), text);
return canvas;
}
Het font wordt geladen, de tekst wordt op de canvas getekend en de canvas wordt terug gegeven.
De DrawText is een methode uit de dll die gecompileerd is uit de eerder genoemde library van Henner Zeller.
Scrolling tekst
Scrolling tekst werkt hetzelfde als de gewone tekst, alleen de tekst beweegt (scrolt) over het scherm.
public void ScrollText(string text, CancellationToken cancellationToken)
{
text = text ?? "This is a scrolling text.";
var canvas = Matrix.CreateOffscreenCanvas();
var font = new RGBLedFont("fonts/6x10.bdf");
var textLength = canvas.DrawText(font, 1, 6, new Color(0, 255, 0), text);
canvas = Matrix.CreateOffscreenCanvas();
int animationCount = 0;
while (animationCount < 5 && !cancellationToken.IsCancellationRequested)
{
var x = canvas.Width;
canvas.Clear();
while (x > -textLength) {
canvas.DrawText(font, x, 20, new Color(0, 255, 0), text);
x -= 1;
canvas = SwapCanvas(canvas);
Thread.Sleep(50);
}
animationCount++;
x = canvas.Width;
}
}
De canvas wordt aangemaakt, het font geladen en de lengte van de tekst bepaald door te tekenen op de canvas.
De tekst wordt 5 keer gescrold door het scherm, en bij elke animatie wordt de tekst telkens opnieuw getekend op het scherm maar dan 1 pixel naar links. Dit geeft de illusie van een bewegende tekst: het scrollen.
Issues
Toen ik eenmaal wat ideeën had uitgeschreven in code was het tijd om te testen of het werkt. Ik kreeg netjes het plaatje te zien op het scherm, of de tekst. Zelfs gifjes werkten, maar meerdere commando’s achter elkaar leken niet te werken. De applicatie bleef hangen.
In de logging stond een foutmelding dat de applicatie niet de juiste rechten had bij een volgend commando. Multi-threading was een issue hier. Er moest één verbinding komen met het scherm en niet elke keer een nieuwe. Gelukkig is hier een simpel pattern voor, de singleton. Dit loste de problemen op en achtereen volgende commando’s werden goed verwerkt.
GitHub
De uiteindelijke API, met wat uitleg over de endpoints is te vinden op GitHub: https://github.com/marcokreeft87/pixel-sharp
Werkend scherm
We helpen graag!
Wil jij ook iets als dit laten werken met .NET en kan je daar hulp bij gebruiken? Mijn collega’s en ik helpen graag!
2 minuten lezen
C# 11 is uit en biedt ontwikkelaars een aantal nieuwe functies en verbeteringen die de programmeertaal nog krachtiger maken. Van raw string literals tot pattern matching op Span<char> en ReadOnlySpan<char>, tot generic attributes en required modifiers, deze nieuwe functies maken het schrijven van software sneller, efficiënter en gemakkelijker. In dit artikel werpen we een blik op enkele van de belangrijkste nieuwe functies in C# 11 en hoe ze je kunnen helpen bij het schrijven van code. Dus, als je klaar bent om te ontdekken hoe C# 11 jouw code naar een hoger niveau kan tillen, lees dan verder!
Raw string literals maakt het voor ontwikkelaars mogelijk om string literals te schrijven die meerdere regels kunnen beslaan en regeleinden en witruimte bevatten. Hierdoor is het gemakkelijker om strings op meerdere regels te schrijven zonder regeleinden te hoeven ‘escapen’.
De nieuwe pattern matching functie in C# 11 maakt het mogelijk om te matchen op Span<char> of ReadOnlySpan<char> op een constant string. Hierdoor is het gemakkelijker om te werken met character arrays, vooral wanneer je bewerkingen zoals string vergelijking of substring-extractie moet uitvoeren.
C# 11 introduceert ook list patterns, die het toelaten om op basis van specifieke kenmerken van een lijst te matchen. Dit maakt het gemakkelijker om bepaalde acties uit te voeren afhankelijk van de inhoud van de lijst.
C# 11 introduceert generic attributes, waarmee attributen gedefinieerd kunnen worden die met elk type, inclusief generieke types, kunnen worden gebruikt. Hierdoor is het gemakkelijker om herbruikbare en flexibele attributen te schrijven en informatie over types te verstrekken die door andere delen van uw code kunnen worden gebruikt.
C# 11 introduceert het concept van required modifiers, waarmee aangeven kan worden dat bepaalde properties van een type door alle afgeleide types verplicht moeten worden geïmplementeerd. Dit is nuttig wanneer je er zeker van wilt zijn dat bepaalde leden altijd aanwezig zijn in alle afgeleide types, ongeacht hun implementatie.
C# 11 brengt een aantal handige nieuwe functies en verbeteringen met zich mee. Of je nu werkt met raw string literals, pattern matching op Span<char> of ReadOnlySpan<char>, generic attributes, required modifiers of list pattern, C# 11 maakt het ontwikkelen van software sneller, efficiënter en gemakkelijker. Upgrade nu naar C# 11 en ontdek de voordelen voor jezelf!
3 minuten lezen
Snel een flexibele en simpele image hosting oplossing opzetten in Azure, hoe doe je dat? Er zijn natuurlijk veel verschillende opties. In deze blog gebruik ik een Storage Account en een Content Delivery Network (Front Door and CDN profiles). De combinatie het storage account en het CDN geeft de mogelijkheid om grote hoeveelheden afbeeldingen en andere bestanden zo snel mogelijk bij de eindgebruiker te krijgen.
Voor dit stappenplan is er vanuit gegaan dat er al een Azure subscription met de benodigde opties is opgezet en basiskennis van de Azure portal bekend is. Volg deze link voor meer informatie over het opzetten van een Azure subscription.
Voeg een nieuw Storage Account resource toe aan je Azure subscription. Maak hier indien gewenst een nieuwe resource groep voor aan. De volgende instellingen zijn belangrijk:
Zodra het storage account is aangemaakt, ziet de overview pagina van deze nieuwe resource er als het goed is ongeveer zo uit:
Afbeelding 1. De overview pagina van deze nieuwe resource
Klik vervolgens aan de linkerzijde van het scherm onder Data management op Static website. Activeer op deze pagina de static website optie. Vervolgens zie je hier dat er een nieuwe Azure Storage container is aangemaakt, $web. Daarnaast is ook een Primary endpoint aangemaakt, hiermee kan overal op het internet de $web folder worden bereikt.
Afbeelding 2: Een nieuwe Azure Storage container
Wanneer er afbeeldingen of andere bestanden aanwezig zijn in de container, zijn deze nu al te bereiken met de volgende url:
{Primary endpoint}/{document name}
Praktisch is dit alles wat nodig is om afbeeldingen te hosten op Azure, maar het kan nog beter!
Een van de opties van het nieuwe storage account is Azure CDN. Klik aan de linkerzijde van het scherm onder Security + networking op Azure CDN.
Creëer hier een nieuw endpoint. Verzin een naam en maak een keuze voor Pricing tier. Voor nu is “Microsoft CDN” voldoende. Het CDN endpoint name is het subdomein dat bij het opvragen van de afbeeldingen in de url zal staan: {subdomein}.azureedge.net, tenzij een ander domein als endpoint gebruikt wordt, hierover onderstaand meer informatie.
Afbeelding 3: New endpoint
Nu kunnen de afbeeldingen via het CDN endpoint worden gedownload:
{subdomein}.azureedge.net/{document name}. Bijvoorbeeld sharevalue.azureedge.net/logo.png
Op het eerste gezicht ziet het resultaat er misschien hetzelfde uit, maar de voordelen van een CDN zijn op grotere schaal pas echt van toepassing. Standaard distribueert Azure CDN wereldwijd de inhoud van het storage account. Zo worden op meerdere servers over heel de wereld afbeeldingen in caches vastgehouden, met als doel om de eindgebruiker, waar dan ook, zo snel mogelijk van dienst te kunnen zijn.
Open voor meer opties voor het configureren van het CDN het endpoint waarmee je de bestanden wilt aanroepen. Mogelijk moet je hier nog een nieuw endpoint aanmaken, dit kan door op het + icoon links boven te klikken.
Afbeelding 4: Configureren van het CDN
Aan de linkerkant zijn vervolgens meerdere opties te zien:
Afbeelding 5: Opties voor het configureren van het CDN
Onder Custom domains kan een eigen domein gebruikt worden, in plaats van de standaard gegeven {subdomein}.azureedge.net.
Een aantal opties die veel impact kunnen hebben op de performance zijn:
Voor het uploaden van bestanden naar het storage account zijn veel opties. Hier is een voorbeeld van code voor het uploaden van een bestand in C#:
Afbeelding 6: Voorbeeld code voor het uploaden van een bestand in C#
In dit voorbeeld wordt gebruik gemaakt van de packages: Azure.Storage.Blobs van Microsoft, en Mimemapping van Matthew Little.
Zo heb je in 4 stappen een oplossing voor image hosting in je web applicatie! Naast deze opstelling zijn er natuurlijk nog veel meer mogelijke keuzes. Met deze oplossing zal je niet snel worden gelimiteerd in capaciteit, en zal de response time voor de meeste doeleinden zeer snel zijn.
3 minuten lezen
Vorige maand was alweer de zesde Tech Thursday die ik organiseerde en de tweede die ook toegankelijk is voor iedereen die geïnteresseerd is; waarom zouden we stoppen met delen bij de voordeur?
Terug naar het onderwerp van de laatste sessie: testen, testen en testen. Aan de titel van het blog kan je lezen dat er één keer testen afgevallen is. Waar ik het bij mijn presentatie over de drie bekendste frameworks had: MS-Test (v2), nUnit en xUnit, spits ik me nu toe tot twee andere interessante ontwikkelingen. Over bUnit heb ik toen ook al gesproken, maar aan het eind van mijn presentatie werd ik door een externe deelnemer gewezen op een andere package, Stryker Mutator.
bUnit
Ik ga het echter eerst over bUnit hebben. Met bUnit kan je Blazor-componenten testen en het werkt altijd in combinatie met één van de andere drie testframeworks. Met bUnit is de Blazor-cirkel rond: van Back-End tot Front-End kan het geheel in C# opgezet worden, inclusief alle (unit)testen.
bUnit is dus bedoeld om een component te renderen en hier acties op uit te voeren en te testen of de output dan aan de verwachting voldoet. En dit kan meegenomen worden in een build pipeline.
Testen met bUnit kan in een normaal C# bestand (.cs) of in een Razor bestand (.razor).
Het voordeel van Razor bestanden is dat het volgende mogelijk is:
@inherits TestContext;
@code
{
[Fact]
public void HelloWorldComponentRendersCorrectly()
{
var cut = RenderComponent<HelloWorld>();
cut.MarkupMatches(@<h1>Hello world from Blazor</h1>);
}
}
De markup kan dus gewoon door middel van het @ teken toegevoegd worden zonder allerlei andere escape tekens. Daarnaast negeert bUnit allerlei opmaak binnen HTML zoals tabs, spaties en enters.
Wil je echter gebruik maken van testen in Razor, dan is het handig om niet met het framework te beginnen (dus niet bijvoorbeeld een xUnit Test Project aanmaken), maar met een ASP.NET Core Empty project. Vervolgens voeg je de gebruikelijke NuGet packages toe om te testen.
Met C# 11 wordt het wellicht weer makkelijker om gewone C#-bestanden te gebruiken, omdat daar een interessante manier wordt geïntroduceerd die “raw string literals” heet .
var location = $$"""
You are at {{{Longitude}}, {{Latitude}}}
""";
Door drie quotes (of meer) te gebruiken, wordt een “raw string literal” gemaakt. Daarnaast heeft het aantal dollartekens aan hoeveel accolades er nodig zijn voor string interpolation.
Zoals het voorbeeld laat zien, is het niet gelijk aan bovenstaande code, maar hierdoor kan het gebruikt van C#-bestanden wel een overweging zijn.
Meer informatie over bUnit vind je hier.
Stryker Mutator
Dat delen met iedereen een voordeel blijkt te hebben, geeft dit deel van de blog wel aan. Stryker was voor mij onbekend en deze interactie was precies waar ik naar zocht toen ik de Tech Thursday toegankelijk wilde maken voor iedereen.
Stryker Mutator is een project van InfoSupport met het doel om de kwaliteit van unit tests te verhogen. Stryker Mutator maakt aanpassingen aan je code waardoor er mutanten ontstaan. Goede unit tests zouden vervolgens moeten falen om gemuteerde code te ontdekken. Als (alle) unit tests slagen dan betekent dit dat de gewijzigde code niet afgedekt wordt door de unit tests.
Een simpel voorbeeld is de volgende code:
public bool IsAdult(int age)
{
return age >= 18;
}
Stryker zal deze code muteren door de code te wijzigen in:
public bool IsAdult(int age)
{
return age < 18;
}
Als je bovenstaande code test, dan krijg je nu een omgekeerd resultaat waardoor je test faalt en de mutant wordt uitgeschakeld.
In combinatie met een goede code coverage tool (zoals bijvoorbeeld SonarQube), is dit een waardevolle tool die ingezet kan worden bij Pull Requests: Stryker kan ingezet worden in build pipelines. Dan wordt niet alleen de code coverage gecontroleerd, maar ook de kwaliteit van de unit test.
Voor meer informatie over Stryker klik hier. Wijzigingen die Stryker Mutator allemaal kan doen, vind je hier en de NuGet package staat hier.
4 minuten lezen
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?
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.
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.
Migration Bundles
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.
Pre-convention modelconfiguratie
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.
UnicodeAttribute
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.
Model building verbeteringen: de kortste configuratie van meer-op-meer-koppelingen
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 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.
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.
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.
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.
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.
3 minuten lezen
Je kan veel van Microsoft zeggen, maar stilgezeten hebben ze dit jaar in ieder geval niet. Op 5 Oktober lanceert Microsoft Windows 11. Een maand later, op 8 november, wordt Visual Studio 2022 gelanceerd en de dag daarna is .NET 6 en C# 10 beschikbaar.
In deze blog gaat het over de laatste datum. De lancering van .NET 6 wordt gevierd met een drie dagen durende conferentie op dotnetconf.net. Om dinsdag om 17:00 begint het met de keynote en de laatste sessie eindigt op vrijdagochtend om 02:00.
Gedurende deze drie dagen zijn er 83 sessies, totaal meer dan 40 uur. Ik denk dat iedereen wel een goede reden heeft om niet al deze sessies te bekijken. Aan de andere kant wil je wel weten wat je kan verwachten van .NET 6 en C# 10.
Daarom in deze blog de must-watch sessies.
Dinsdag 9 november
17:00 – De Keynote
De enige sessie van een uur waarin Scott Hunter en z’n team al het grote nieuws van .NET 6 presenteert.
18:30 – What’s new in C# 10
Deze sessie is belangrijk voor C# developers aangezien C# 10 handige nieuwe functies heeft.
19:00 – Enterprise-grade Blazor apps with .NET 6
Dat Microsoft Blazor nog steeds serieus neemt blijkt wel uit het feit dat 14 van de 83 sessies over Blazor gaan. Deze sessie worden nieuwe features gepresenteerd.
22:00 – Minimal APIs in .NET 6
In deze sessie wordt gedemonstreerd hoe kleine HTTP APIs gebouwd kunnen worden met “low-ceremony”.
0:00 – Upgrading from .NET Framework to .NET 6
Een belangrijke sessie voor gebruikers van .NET Framework waarin de voordelen van .NET 6 ten opzichte van .NET Framework besproken worden.
1:30 – .NET Everywhere - Windows, Linux, and Beyond
Rocksterren komen altijd aan het eind van de avond en Scott Hanselman is natuurlijk de rockster van Microsoft. Deze sessies zijn altijd de moeite waard.
Woensdag 10 november
Op woensdag gaan de sessies om 16:00 weer verder waarbij begonnen wordt met CodeParty Day 2. Daarna gaan de sessies in één keer door tot 2:00 in de nacht van donderdag op vrijdag.
Donderdag 11 november
8:30 – Practical tips to elevate your UX and accessibility
Ik heb al eerder sessies van Jessica Engström gezien en deze sessies geven altijd goed inzicht hoe UX-ontwerpen verbeterd kunnen worden.
11:30 – JavaScript frontend development with ASP.NET Core in .NET 6
Veel webapplicaties die tegenwoordig gebouwd worden, hebben een .NET 6 API back-end met een Javascript framework, zoals Angular, als Front-End. In deze sessies worden verbeteringen gedemonstreerd.
14:30 – 30 Minutes of Testing in .NET
Testen is een belangrijk onderdeel van software ontwikkeling. In deze sessie passeren verschillende soorten tests de revue met voorbeelden hoe ze in ASP.NET projecten kunnen worden toegepast.
21:30 – Cross Platform Database Support On Steroids
Deze sessie heb ik toegevoegd, zodat het hele pallet van database tot Front-End met UX in de must-watch lijst staat. In deze sessie wordt EF Core gebruikt om te integreren met verschillende database soorten, zoals SQL Server, MySQL en PostgreSQL.
1:00 – Host, deploy and scale ASP.NET Core Blazor Server
In deze sessie wordt naar verschillende Blazor Server configuraties gekeken.
Uiteraard zijn er veel meer interessante sessies, maar met bovenstaande sessies krijg je een redelijk goed beeld welke innovaties er met .NET 6 nieuw bijgekomen zijn. Alle sessies zijn ook op een later moment terug te kijken. Vorig jaar zagen we dat YouTube de beste feed was om te volgen.
Alle sessies zijn ook terug te vinden op dotnetconf.net.