Deze handleiding maakt deel uit van het programmeertraject:
Inhoud
- Wat vooraf ging
- Wat is Entity Framework?
- Waarom Entity Framework?
- De evolutie van Entity Framework
- Database-First of Code-First
- Een Model aanmaken
- Conventies bij het mappen naar de databank
Wat vooraf ging
- U bent vertrouwd met Klassen.
- U bent vertrouwd met de MVVM architectuur.
Wat is Entity Framework?
Het Entity Framework, ontwikkeld door Microsoft, is een reeks technologieën die de ontwikkeling van gegevensgeoriënteerde applicaties ondersteunen. Het Entity Framework stelt ontwikkelaars in staat om te werken met gegevens op het niveau van de entiteiten, zonder zich bezig te hoeven houden met de onderliggende databasetabellen en kolommen waarin deze gegevens zijn opgeslagen.
Entity Framework is een object-relationele mapper (ORM) die een brug bouwt tussen de objectgeoriënteerde wereld van .NET Framework-ontwikkelaars en de wereld van relationele databases. Hierdoor kunnen ontwikkelaars met behulp van bekende objectgerichte technieken zoals (domein specifieke) objecten en eigenschappen werken zonder dat ze zich zorgen hoeven te maken over de onderliggende databasetabellen en kolommen waarin deze gegevens zijn opgeslagen. Ontwikkelaars kunnen bewerkingen voor gegevenstoegang (CRUD, Create, Read, Update, Delete) uitvoeren tegen het conceptuele model en Entity Framework vertaalt de bewerkingen naar relationele databaseacties.
- Het Entity Framework vertrekt vanuit het Entity Data Model (EDM) dat bekomen wordt via het ontwerpen van een Entity Relationship Diagram (ERD).
- Een ERD levert ons entiteiten op met hun attributies (properties) en relaties. Iedere entiteit, met zijn attributies (properties) en relaties is een model (de M van MVVM), een klasse.
- Dit model, of indien er meerdere entiteiten zijn, deze modellen, worden nadien “gemapt” naar een database schema dat gebruikt wordt om de databank te ontwerpen.
Met het Entity Framework kunnen ontwikkelaars op een hoger niveau van abstractie werken wanneer ze met gegevens omgaan en kunnen ze gegevensgeoriënteerde applicaties maken en onderhouden met minder code dan in traditionele applicaties.
Waarom Entity Framework?
Entity Framework is slechts één van de benaderingen om gegevensgeoriënteerde applicaties te bouwen binnen .NET (en bij uitbeiding Xamarin).
De keuze viel op Entity Framework omdat:
- Entity Framework sluit aan bij de reeds gekende Entity Relationship Diagram (ERD).
- Entity Framework ondersteunt een hele resem aan database providers zoals.
- SQL Server
- MySQL
- Oracle
- SQLite
- Firebird
- Jet (Microsoft Access)
- … en de lijst breidt nog steeds uit.
- Entity Framework is niet Xamarin specifiek maar wordt ook gebruikt in ASP.NET, UWP,… U leert dus iets dat u kunt hergebruiken in andere omgevingen.
De evolutie van Entity Framework
Entity Framework zag het levenslicht op 11 augustus 2008 als onderdeel van Visual Studio 2008 Service Pack 1 en .NET Framework 3.5 Service Pack 1.
Bijna jaarlijks kwam er een nieuwe versie uit tot en met Entity Framework 6 (of kortwerg EF 6) in 2013 als onderdeel van Visual Studio 2012 en .NET Framework 4.5.
Entity Framework 6 was echter enkel bruikbaar op Windows. Met de komst van steeds meer mobiele toestellen was het tijd voor een volgende stap in de evolutie van Entity Framework en dit werd in 2016 Entity Framework Core als onderdeel van .NET Core.
Entity Framework Core (of kortweg EF Core) is een lichtere, uitbreidbare, cross platform versie van EF 6 (dat enkel nog onderhouden wordt maar geen nieuwe versie meer zal krijgen).
Database-First of Code-First
Entity Framework Core kent twee benaderingen om met databanken om te gaan:
- Database-First
- Code-First
Database-First
In de Database-First benadering vertrekt u van een bestaande databank. Vanuit deze databank worden dan, via “reverse engineering” de nodige modellen gegenereerd (via Scaffold-DbContext
). Klik hier voor een uitgewerkt voorbeeld.
Code-First
In de Code-First benadering vertrekt u vanuit de bestaande geprogrammeerde modellen en wordt de databank automatisch gegenereerd.
Als u nadien aanpassing maakt aan de modellen (bv. een veld toevoegt) moet er een nieuwe migratie plaatsvinden zodat de aanpassingen kunnen worden doorgevoerd met behoud van de reeds ingevoerde gegevens.
Migratie is de methode die Entity Framework gebruikt om, na publicatie, wijzigingen aan de databank door te voeren, met behoud van de reeds toegevoegde gegevens of anders gezegd, het synchroniseren tussen het Model en de databank met behoudt van de ingevoerde gegevens.
Migratie zal nader besproken worden in een eigen handleiding.
Een Model aanmaken
Laten we eens een model bekijken dat via Code-First als basis dient voor de databank.
We wensen een Blog en bijhorende Posten bij te houden.
Entiteitklassen
De Entiteitklassen bevatten de entiteiten met hun attributen en relaties.
public class Blog { public int BlogId { get; set; } public string Url { get; set; } } public class Post { public int PostId { get; set; } public string Title { get; set; } public string Content { get; set; } }
Er is een één op veel relaties tussen Blog een Post. Op een Blog staan één of meer Posten en een Post staat maar op één Blog.
Een relatie kan op meerdere manieren worden gelegd maar de meest eenvoudige is de volgende: voer aan de entiteit Blog een lijst van Posten toe public List Posts { get; set; }
, de zogenaamde navigatie property. Op deze manier geef je aan dat één Blog veel Posten kan bevatten.
public class Blog { public int BlogId { get; set; } public string Url { get; set; } public List<Post> Posts { get; set; } } public class Post { public int PostId { get; set; } public string Title { get; set; } public string Content { get; set; } }
Het meest gebruikte patroon is echter het onderstaande, waarin aan de veel-kant ook een verwijzing wordt opgenomen naar de één-kant, de zogenaamde inverse naviagation property, al dan niet met het opnemen van een Foreign key (in onderstaand voorbeeld is de Foreign Key public int BlogId { get; set; }
opgenomen maar hij mag ook worden weggelaten).
public class Blog { public int BlogId { get; set; } public string Url { get; set; } public List<Post> Posts { get; set; } } public class Post { public int PostId { get; set; } public string Title { get; set; } public string Content { get; set; } public int BlogId { get; set; } public Blog Blog { get; set; } }
Maar waarom zou je die extra informatie meegeven?
Vergeet niet dat deze code nog moet “gemapt” worden naar een achterliggende databank, dus hoe meer wij reeds meegeven in code, hoe minder Entity Framework moet “interpreteren”.
Contextklasse
De Contextklasse is een belangrijke klasse binnen Entity Framework. Deze klasse erft over van DbContext
en verzorgt de communicatie met de achterliggende databank:
- Legt de connectie met de databank
- Configureert de modellen en relaties
- Bevraagt (query) de databank
- Bewaart gegevens in de databank
- …
using Microsoft.EntityFrameworkCore; public class BlogContext : DbContext { public BlogContext() { } //entiteiten public DbSet<Blog> Blogs { get; set; } public DbSet<Post> Posts { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { } }
- Merk de overerving van
DbContext
op. - De DbSet properties verwijzen naar de entiteiten die in de databank opgenomen worden.
- De
OnConfiguring(DbContextOptionsBuilder optionsBuilder)
methode bevat de configuratie van de databank. - De
OnModelCreating(ModelBuilder modelBuilder)
methode laat toe de modellen te creëren op basis van de Fluent Api.
Onderstaande code zal een databank aanmaken met de naam BlogDB in SQLServer Express dat lokaal zal draaien op onze pc.
using Microsoft.EntityFrameworkCore; public class BlogContext : DbContext { public BlogContext() { } //entiteiten public DbSet<Blog> Blogs { get; set; } public DbSet<Post> Posts { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer(@"Server=.\SQLEXPRESS;Database=BlogDB;Trusted_Connection=True;"); } protected override void OnModelCreating(ModelBuilder modelBuilder) { } }
Conventies bij het mappen naar de databank
Conventies zijn standaardregels waarmee Entity Framework een model bouwt op basis van uw entiteit (domain) klassen. We gaan in de loop van de volgende handleidingen nog vaker spreken over conventies maar ik geef er hier toch al een paar mee:
Standaard conventies | Omschrijving |
Schema | EF creëert alle DB objecten in het dbo-schema. |
Tabelnaam | <Entity Class Name> + ‘s’
EF creëert de tabel op basis van de entiteit klasnaam + een “s” (het Engelse meervoud). Bijvoorbeeld: de entiteit (domain) klasse |
Primary key naam | 1) Id 2) <Entity Class Name> + “Id” (case insensitive)EF creëert een primary key kolom voor de property Id of voor de property <Entity Class Name> + “Id” (case insensitive). |
Foreign key property Naam | EF kijkt uit naar een Foreign key property met dezelfde naam als een principal entity primary key name.
Als een Foreign key property niet bestaat, dan creëert EF een Foreign Key kolom in de tabel met: <Dependent Navigation Property Name> + “_” + <Principal Entity Primary Key Property Name> Bijvoorbeeld EF creëert de |
Not Null Column | EF creëert Not Null kolommen voor Primary Key properties en non-nullable value type properties bv. int, float, decimal, datetime etc. |
Cascade delete | Standaard is Cascade deleting actief voor alle relaties.
Dus, als u een Blog verwijdert worden alle gerelateerde posten eveneens verwijderd. |
Onderstaande tabel toont de mapping van datatypen.
C# Data Type | Mapping naar SQL Server Data Type |
int | int |
string | nvarchar(Max) |
decimal | decimal(18,2) |
float | real |
byte[] | varbinary(Max) |
datetime | datetime |
bool | bit |
byte | tinyint |
short | smallint |
long | bigint |
double | float |
char | geen mapping |
sbyte | geen mapping (throws exception) |
object | geen mapping |