EF Core 6 new features and changes for .NET 6
Published: Sunday 12 December 2021
EF Core 6 is upon us, and unless you have been living under a rock, you would know that .NET 6 was launched last month, and there are a number of changes were implemented to Entity Framework Core as part of the update. And we are going to have a look at some of them.
Feature #1 - Migration bundles
Entity Framework's migrations have been a familiar feature for code-first integration. As new features get implemented into an application, it's possible that new entities and properties are added to support these. Therefore, the database schema needs to kept in sync with the application.
Bundle-Migration
An unexpected error
However, when we ran this script, we are greeted with the following error:
Build failed. Use --verbose to see errors.
So we ran it with the -verbose parameter to see if that helped us.
Bundle-Migration -verbose
We had a slightly more descriptive error, but still not very helpful.
The process cannot access the file 'RoundTheCode.EFCore.dll' because it is being used by another process. [RoundTheCode.EFCore.csproj]
Afterwards, we tried to run it in Powershell (in admin mode) using the dotnet command line:
dotnet ef migrations bundle --verbose
A resolution
Again, we were greeted with the same errors as above. The way we managed to get around it was to append the --configuration parameter to the dotnet command line script, and ensured that it contained anything apart from debug or release.
dotnet ef migrations bundle --verbose --configuration abc
This worked for us, and generated a efbundles.exe file. We can then run that file and it would update our database schema with the entities and properties within our application.
Feature #2 - Temporal tables
Temporal tables were introduced in SQL Server 2016. These tables have the ability to keep a full history of changes within a table. This means that if we need to know what data was stored at any point in time, we can go ahead and query it.
DbContext, we have set up a Player and Team entity, and we are now going to go ahead and make them temporal. We can do that by overriding the OnModelCreating method and use the IsTemporal method:
public class EfCoreDbContext : DbContext
{
...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Player>()
.ToTable(action =>
{
action.IsTemporal();
});
modelBuilder.Entity<Team>()
.ToTable(action =>
{
action.IsTemporal();
});
}
}
Now that we've made that change, we need to add a migration for it. In Visual Studio 2022, we can go to Tools > NuGet Package Manager > Package Manager Console, and run the following script:
Add-Migration Temporal
Assuming we are not using migration bundles, we need to update the database and we can run the following script in Package Manager Console to do that:
Update-Database
Now that we've set up temporal tables, we can query the history of changes. We can do that by running a query similar to the following:
[ApiController]
public class TestController : ControllerBase
{
...
[HttpGet("sample")]
public virtual async Task<ActionResult<List<Team>>> GetSample()
{
var teams = await _dbContext.Teams.TemporalAll().Where(x => x.Id == 1).ToListAsync();
return Ok(teams);
}
}
The TemporalAll operation retrieves the full history of changes for that particular table. If we wish to be date specific, we can use the TemporalAsOf operation, passing in the UTC date as a parameter. There is also a TemporalBetween, TemporalContainedIn and TemporalFromTo operation that we can use.
Feature #3 - Pre-convention model configuration
Regular users of EF Core will be familiar with having to set a max length for each string in an entity. Otherwise, each string would be migrated as a NVARCHAR(max) column type in SQL Server. But with EF Core 6, we can set a convention for this so we don't have to set it for each individual property.
ConfigureConventions method in our DbContext and set our conventions within that.
using RoundTheCode.EfCore.Entities;
namespace RoundTheCode.EfCore
{
public class EfCoreDbContext : DbContext
{
...
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
// Pre-convention model configuration goes here
configurationBuilder.Properties<string>().AreUnicode(true).HaveMaxLength(300);
}
...
}
}
Once we've set this up, we then need to add a migration for it. The migration will update all our string property to ensure that those columns have a maximum length of 300 characters.
Add-Migration Conventions
Afterwards, it's a case of updating the database, either through migration bundles or by running the Update-Database command in Package Manager Console.
ConfigureConventions method.
See EF Core updates in action
Check out our video where we showcase these EF Core 6 updates in action:
In addition, if you can download the code example to try out these EF Core 6 updates for yourself.
Related articles