What's New in EF Core 6.0

SQL Server temporal tables:

SQL Server temporal tables automatically keep track of all data ever stored in a table, even after that data has been updated or deleted. This is achieved by creating a parallel "history table" into which timestamped historical data is stored whenever a change is made to the main table. This allows historical data to be queried, such as for auditing, or restored, such as for recovery after accidental mutation or deletion.

EF Core now supports:

  • The creation of temporal tables using Migrations
  • Transformation of existing tables into temporal tables, again using Migrations
  • Querying historical data
  • Restoring data from some point in the past
 
modelBuilder
    .Entity<Employee>()
    .ToTable("Employees", b => b.IsTemporal());
When using EF Core to create the database, the new table will be configured as a temporal table with the SQL Server defaults for the timestamps and history table. For example, consider an Employee entity type:
 
modelBuilder
    .Entity<Employee>()
    .ToTable(
        "Employees",
        b => b.IsTemporal(
            b =>
            {
                b.HasPeriodStart("ValidFrom");
                b.HasPeriodEnd("ValidTo");
                b.UseHistoryTable("EmployeeHistoricalData");
            }));

EF Core Minimal API:

.NET Core 6.0 includes updated templates that feature simplified "minimal APIs" which remove a lot of the boilerplate code traditionally needed in .NET applications.

EF Core 6.0 contains a new extension method that registers a DbContext type and supplies the configuration for a database provider in a single line. For example:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSqlite<MyDbContext>("Data Source=mydatabase.db");

DbContext factory improvements:

Sometimes it is useful to have both a DbContext type and a factory for contexts of that type both registered in the applications dependency injection (D.I.) container. This allows, for example, a scoped instance of the DbContext to be resolved from the request scope, while the factory can be used to create multiple independent instances when needed.

To support this, AddDbContextFactory now also registers the DbContext type as a scoped service. For example, consider this registration in the application's D.I. container:

var container = services
    .AddDbContextFactory<SomeDbContext>(
        builder => builder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFCoreSample"))
    .BuildServiceProvider();

DbContextFactory ignores DbContext parameterless constructor:

EF Core 6.0 now allows both a parameterless DbContext constructor, and a constructor that takes DbContextOptions to be used on the same context type when the factory is registered through AddDbContextFactory. For example, the context used in the examples above contains both constructors:

public class SomeDbContext : DbContext
{
    public SomeDbContext()
    {
    }

    public SomeDbContext(DbContextOptions<SomeDbContext> options)
        : base(options)
    {
    }
    
    public DbSet<Blog> Blogs { get; set; }
}

Translate Substring with single parameter:

var result = context.Customers
    .Select(a => new { Name = a.Name.Substring(3) })
    .FirstOrDefault(a => a.Name == "hur");

Raw SQL queries with FromSql:

var maxAngle = 60;
var results = await context.Triangles.FromSqlRaw(
        @"SELECT * FROM root c WHERE c[""Angle1""] <= {0} OR c[""Angle2""] <= {0}", maxAngle)
    .ToListAsync();

 

 

 

Related posts

Add comment

Loading