In this module you will learn how to define a data structure using Entity Framework (EF) Core. https://docs.microsoft.com/en-us/ef/core/
With EF Core, data access is performed using a model. A model is made up of entity classes and a context object that represents a session with the database. The context object allows querying and saving data. If you're using a relational database, EF Core can create and update tables for your entities via migrations.
- Creating and configuring a model
- DbContext configuration
- Fluent API vs Data Annotations
- Primary & alternate keys
- Indexes
- Spatial Data
- Migrations
You'll need to set up your machine to run .NET, including the C# 10.0 compiler. Download & install the .NET 6 SDK.
This tutorial assumes you're familiar with C#, .NET and the concept of object-relational mapping (ORM).
It is recommended you read through the Entity Framework Core documentation before starting the assignments.
We are going to create an application that keeps track of the modes of transport that a company's employees use to commute to work daily. The full solution will include:
- Data project: defines the data structure
- Domain project: business logic implementations
- WebApplication project: includes the web API's & backoffice web application to manage the employee data
- Mobile app project: will be used by the employees to input the mode of travel for their daily commute
Let's start with implementing the data layer.
- Create a new class library project, targeting .NET6
- Opt in the nullable reference types feature
https://docs.microsoft.com/en-us/ef/core/get-started/overview/install
To add EF Core to an application, install the NuGet package for the database provider you want to use.
To install or update NuGet packages, you can use the .NET Core command-line interface (CLI), the Visual Studio Package Manager Dialog, or the Visual Studio Package Manager Console.
NuGet packages to install:
- Microsoft.EntityFrameworkCore
- Microsoft.EntityFrameworkCore.Design
- Microsoft.EntityFrameworkCore.SqlServer
- Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite
To set up SQL Server on your development environment, go to https://www.microsoft.com/en-us/sql-server/developer-get-started/ and select the programming language (C#) & the operating system of your development environment.
Then, simply follow the instructions to set up a SQL Server locally.
After you have the SQL Server set up, you should have a database up & running on your local machine. Now configure the DataContext with the connection string, and enable mapping to spatial types via NetTopologySuite (NTS) https://docs.microsoft.com/en-us/ef/core/modeling/spatial#nettopologysuite
The BaseEntity entity class will serve as a base type for other entity types. The BaseEntity entity has 3 properties:
The Employee entity class inherits from BaseEntity and has properties:
- Id (inherited from BaseEntity)
- CreatedAt (inherited from BaseEntity)
- UpdatedAt (inherited from BaseEntity)
- Name (String, max. 128 characters, index)
- Email (String, max. lenght 128 characters, unique index)
- HomeLocation (Point)
- DefaultWorkLocation (Point)
- DefaultCommuteType (enum CommuteType, see below)
- Commutes (one-to-many relation with Commute entity)
public enum CommuteType
{
Undefined,
Bike,
Car,
CarpoolDriver,
CarpoolPassenger,
PublicTransport,
Train,
Walking,
}
The Commute entity will be used to keep track of the daily commutes reported by employees. Each Employee can have many Commutes.
The Commute entity class inherits from BaseEntity and has properties:
- Id (inherited from BaseEntity)
- CreatedAt (inherited from BaseEntity)
- UpdatedAt (inherited from BaseEntity)
- Employee (relation with Employee entity)
- CommuteType (enum CommuteType, see previous step)
https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/?tabs=dotnet-core-cli
10. Override SaveChangesAsync to automatically set CreatedAt and/or UpdatedAt fields on saving changes
To automatically set the CreatedAt & UpdatedAt fields to the current timestamp, you can override the SaveChangesAsync method in the DataContext class.
Add the following method to the DataContext class:
/// <summary>
/// Automatically set CreatedAt and/or UpdatedAt fields on saving changes
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken))
{
var entries = ChangeTracker
.Entries()
.Where(e => e.Entity is BaseEntity && e.State is EntityState.Added or EntityState.Modified);
foreach (var entityEntry in entries)
{
((BaseEntity)entityEntry.Entity).UpdatedAt = DateTime.UtcNow;
if (entityEntry.State == EntityState.Added)
{
((BaseEntity)entityEntry.Entity).CreatedAt = DateTime.UtcNow;
}
}
return await base.SaveChangesAsync(true, cancellationToken);
}