EF Core migration features that you might not know about
Published: Monday 26 August 2024
There are some invaluable features in Entity Framework that will help you with database migrations.
Entity type configuration
One way of configurating entities in Entity Framework Core is to override the OnModelCreating method in your DbContext and use the ModelBuilder type parameter within it to select the entity and add the configuration.
SocialMedia entity that we want to add to our DbContext. The entity has an Id and Name property.
// SocialMedia.cs
namespace RoundTheCode.HelpfulEfCore.Entities;
public class SocialMedia
{
public int Id { get; set; }
public string? Name { get; set; }
}
We want to configure the Name property so it has a maximum length of 50 characters when we migrate it in the database.
SocialMediaConfiguration class.
IEntityTypeConfiguration interface, passing in the entity that we are configuring as its generic type.
IEntityTypeConfiguration interface has a Configure method which has an EntityTypeBuilder type as the parameter. This is where we can add the configuration.
// SocialMediaConfiguration.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using RoundTheCode.HelpfulEfCore.Entities;
namespace RoundTheCode.HelpfulEfCore.Configuration;
public class SocialMediaConfiguration : IEntityTypeConfiguration<SocialMedia>
{
public void Configure(EntityTypeBuilder<SocialMedia> builder)
{
builder.Property(s => s.Name)
.HasMaxLength(50);
}
}
In-order to add this configuration class to the DbContext, we need to override the OnModelCreating method within it.
ModelBuilder instance as the parameter. We use that and call the ApplyConfigurationsFromAssembly method, passing in the assembly location of the configuration class for each entity.
SocialMediaConfiguration class has a namespace of RoundTheCode.HelpfulEfCore.Configuration, we can load in the RoundTheCode.HelpfulEfCore assembly, and pass that in as the parameter to the ApplyConfigurationsFromAssembly method.
IEntityTypeConfiguration interface and are inside the RoundTheCode.HelpfulEfCore assembly will automatically be configured to that DbContext when adding a new migration.
// MyDbContext.cs
using System.Reflection;
public class MyDbContext : DbContext
{
...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.Load("RoundTheCode.HelpfulEfCore"));
base.OnModelCreating(modelBuilder);
}
}
With this in place, we can open up the Package Manager Console in Visual Studio by going to Tools, NuGet Package Manager and Package Manager Console.
DbContext, call Add-Migration and give it a name. For example:
Add-Migration SocialMediaTable
Calling the Update-Database command in Package Manager Console will apply that migration to the database.
Seed data
Seed data is another tool that can be used with EF Core migrations. This populates the database with an initial set of data for an entity.
SocialMediaConfiguration class, we can call the HasData method in the EntityTypeBuilder type parameter to add this data to the database.
SocialMedia table, explicitly specifying the Id for each of them.
// SocialMediaConfiguration.cs
public class SocialMediaConfiguration : IEntityTypeConfiguration<SocialMedia>
{
public void Configure(EntityTypeBuilder<SocialMedia> builder)
{
...
builder.HasData(new SocialMedia
{
Id = 1,
Name = "Facebook"
}, new SocialMedia
{
Id = 2,
Name = "Instagram"
}, new SocialMedia
{
Id = 3,
Name = "LinkedIn"
});
}
}
We can then add another migration script by opening the Package Manager Console and running the Add-Migration command.
Add-Migration SocialMediaSeedData
To update the database, we then call Update-Database in Package Manager Console.
Value converters
Value converters allows you to convert data into a specific format in the database, and convert it back when its used in the application.
Product entity.
// Product.cs
public class Product
{
public int Id { get; set; }
public string? Name { get; set; }
public DateTime Created { get; set; }
}
This entity contains a Created property which has a DateTime type.
DateTimeUtcConverter class, inheriting the ValueConverter class with two generic types.
DateTime types, we use DateTime for both generic types.
DateTimeUtcConverter class, calling a base constructor in ValueConverter.
// DateTimeUtcConverter.cs
public class DateTimeUtcConverter : ValueConverter<DateTime, DateTime>
{
public DateTimeUtcConverter() : base(
date => date.ToUniversalTime(),
date => DateTime.SpecifyKind(date, DateTimeKind.Utc).ToLocalTime()
)
{
}
}
To configure the DateTimeUtcConverter class on a property in an entity, we call it in the configuration class using the EntityTypeBuilder type and calling the HasConversion method.
// ProductConfiguration.cs
public class ProductConfiguration : IEntityTypeConfiguration<Product>
{
public void Configure(EntityTypeBuilder<Product> builder)
{
builder.Property(s => s.Name)
.HasMaxLength(50);
builder.Property(s => s.Created)
.HasConversion(new DateTimeUtcConverter());
}
}
Run a SQL command
SQL commands can also be run when applying a migration.
Add-Migration command in Package Manager Console.
Add-Migration ProductSql
From there, we can add the migration scripts to the Up method by calling the Sql method in the MigrationBuilder parameter type.
Product table.
// ProductSql.cs
public partial class ProductSql : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("INSERT INTO dbo.Product (Name, Created) VALUES ('Book', GETUTCDATE())");
migrationBuilder.Sql("INSERT INTO dbo.Product (Name, Created) VALUES ('Television', GETUTCDATE())");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
To run these SQL commands as part of the migration, you just call the Update-Database command in Package Manager Console and it will apply the changes.
Watch the video
Watch our video where we go through each of these EF Core migration features and how they work.
If you want to know more about Entity Framework Core migrations, you can watch our six-part series on how to Get Started with EF Core.
DbContext and how to insert, update and delete a record from the database.Related articles
Why your EF Core queries are slow and how to fix them
Discover why your EF Core queries are slow and learn practical fixes to improve performance, reduce query times, and optimise your .NET applications.