Announcing Entity Framework Core 6.0 Preview 1

Jeremy Likness

Jeremy

Today, the Entity Framework Core team announces the first preview release of EF Core 6.0. This release includes new attributes, built-in functions, and database-specific improvements to SQLite and SQL Server capabilities.

Prerequisites

  • EF Core 6.0 currently targets .NET 5. This will likely be updated to .NET 6 as we near the release. EF Core 6.0 does not target any .NET Standard version; for more information see the future of .NET Standard.
  • EF Core 6.0 will not run on .NET Framework.

How to get EF Core 6.0 previews

EF Core is distributed exclusively as a set of NuGet packages. For example, to add the SQL Server provider to your project, you can use the following command using the dotnet tool:

dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 6.0.0-preview.1.21102.2

This following table links to the preview 1 versions of the EF Core packages and describes what they are used for.

PackagePurpose
Microsoft.EntityFrameworkCoreThe main EF Core package that is independent of specific database providers
Microsoft.EntityFrameworkCore.SqlServerDatabase provider for Microsoft SQL Server and SQL Azure
Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuiteSQL Server support for spatial types
Microsoft.EntityFrameworkCore.SqliteDatabase provider for SQLite that includes the native binary for the database engine
Microsoft.EntityFrameworkCore.Sqlite.CoreDatabase provider for SQLite without a packaged native binary
Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuiteSQLite support for spatial types
Microsoft.EntityFrameworkCore.CosmosDatabase provider for Azure Cosmos DB
Microsoft.EntityFrameworkCore.InMemoryThe in-memory database provider
Microsoft.EntityFrameworkCore.ToolsEF Core PowerShell commands for the Visual Studio Package Manager Console; use this to integrate tools like scaffolding and migrations with Visual Studio
Microsoft.EntityFrameworkCore.DesignShared design-time components for EF Core tools
Microsoft.EntityFrameworkCore.ProxiesLazy-loading and change-tracking proxies
Microsoft.EntityFrameworkCore.AbstractionsDecoupled EF Core abstractions; use this for features like extended data annotations defined by EF Core
Microsoft.EntityFrameworkCore.RelationalShared EF Core components for relational database providers
Microsoft.EntityFrameworkCore.AnalyzersC# analyzers for EF Core

We also published the 6.0 preview 1 release of the Microsoft.Data.Sqlite.Core provider for ADO.NET.

Installing the EF Core Command Line Interface (CLI)

As with EF Core 3.0 and 3.1, the EF Core CLI is no longer included in the .NET Core SDK. Before you can execute EF Core migration or scaffolding commands, you’ll have to install this package as either a global or local tool.

To install the preview tool globally, first uninstall any existing version with:

dotnet tool uninstall --global dotnet-ef

Then install with:

dotnet tool install --global dotnet-ef --version 6.0.0-preview.1.21102.2

It’s possible to use this new version of the EF Core CLI with projects that use older versions of the EF Core runtime.


What’s New in EF Core 6 Preview 1

We maintain documentation covering new features introduced into each preview.

Some of the highlights from preview 1 are called out below. This preview also includes several bug fixes.

TIP You can run and debug into all the preview 1 samples shown below by downloading the sample code from GitHub.

UnicodeAttribute

GitHub Issue: #19794. This feature was contributed by @RaymondHuy.

Starting with EF Core 6.0, a string property can now be mapped to a non-Unicode column using a mapping attribute without specifying the database type directly. For example, consider a Book entity type with a property for the International Standard Book Number (ISBN) in the form “ISBN 978-3-16-148410-0”:

    public class Book
    {
        public int Id { get; set; }
        public string Title { get; set; }

        [Unicode(false)]
        [MaxLength(22)]
        public string Isbn { get; set; }
    }

Since ISBNs cannot contain any non-unicode characters, the Unicode attribute will cause a non-Unicode string type to be used. In addition, MaxLength is used to limit the size of the database column. For example, when using SQL Server, this results in a database column of varchar(22):

CREATE TABLE [Book] (
    [Id] int NOT NULL IDENTITY,
    [Title] nvarchar(max) NULL,
    [Isbn] varchar(22) NULL,
    CONSTRAINT [PK_Book] PRIMARY KEY ([Id]));

NOTE EF Core maps string properties to Unicode columns by default. UnicodeAttribute is ignored when the database system supports only Unicode types.

PrecisionAttribute

GitHub Issue: #17914. This feature was contributed by @RaymondHuy.

The precision and scale of a database column can now be configured using mapping attributes without specifying the database type directly. For example, consider a Product entity type with a decimal Price property:

    public class Product
    {
        public int Id { get; set; }

        [Precision(precision: 10, scale: 2)]
        public decimal Price { get; set; }
    }

EF Core will map this property to a database column with precision 10 and scale 2. For example, on SQL Server:

CREATE TABLE [Product] (
    [Id] int NOT NULL IDENTITY,
    [Price] decimal(10,2) NOT NULL,
    CONSTRAINT [PK_Product] PRIMARY KEY ([Id]));

EntityTypeConfigurationAttribute

GitHub Issue: #23163. This feature was contributed by @KaloyanIT.

IEntityTypeConfiguration instances allow ModelBuilder configuration for a each entity type to be contained in its own configuration class. For example:

public class BookConfiguration : IEntityTypeConfiguration<Book>
{
    public void Configure(EntityTypeBuilder<Book> builder)
    {
        builder
            .Property(e => e.Isbn)
            .IsUnicode(false)
            .HasMaxLength(22);
    }
}

Normally, this configuration class must be instantiated and called into from OnModelCreating. For example:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    new BookConfiguration().Configure(modelBuilder.Entity<Book>());
}

Starting with EF Core 6.0, an EntityTypeConfigurationAttribute can be placed on the entity type such that EF Core can find and use appropriate configuration. For example:

[EntityTypeConfiguration(typeof(BookConfiguration))]
public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Isbn { get; set; }
}

This attribute means that EF Core will use the specified IEntityTypeConfiguration implementation whenever the Book entity type is included in a model. The entity type is included in a model using one of the normal mechanisms. For example, by creating a DbSet property for the entity type:

public class BooksContext : DbContext
{
    public DbSet<Book> Books { get; set; }

    //...

Or by registering it in OnModelCreating:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Book>();
}

NOTE EntityTypeConfigurationAttribute types will not be automatically discovered in an assembly. Entity types must be added to the model before the attribute will be discovered on that entity type.

Translate ToString on SQLite

GitHub Issue: #17223. This feature was contributed by @ralmsdeveloper.

Calls to ToString are now translated to SQL when using the SQLite database provider. This can be useful for text searches involving non-string columns. For example, consider a User entity type that stores phone numbers as numeric values:

    public class User
    {
        public int Id { get; set; }
        public string Username { get; set; }
        public long PhoneNumber { get; set; }
    }

ToString can be used to convert the number to a string in the database. We can then use this string with a function such as LIKE to find numbers that match a pattern. For example, to find all numbers containing 555:

var users = context.Users.Where(u => EF.Functions.Like(u.PhoneNumber.ToString(), "%555%")).ToList();

This translates to the following SQL when using a SQLite database:

SELECT COUNT(*)
FROM "Users" AS "u"
WHERE CAST("u"."PhoneNumber" AS TEXT) LIKE '%555%'

Note that translation of ToString for SQL Server is already supported in EF Core 5.0, and may also be supported by other database providers.

EF.Functions.Random

GitHub Issue: #16141. This feature was contributed by @RaymondHuy.

EF.Functions.Random maps to a database function returning a pseudo-random number between 0 and 1 exclusive. Translations have been implemented in the EF Core repo for SQL Server, SQLite, and Cosmos. For example, consider a User entity type with a Popularity property:

    public class User
    {
        public int Id { get; set; }
        public string Username { get; set; }
        public int Popularity { get; set; }
    }

Popularity can have values from 1 to 5 inclusive. Using EF.Functions.Random we can write a query to return all users with a randomly chosen popularity:

var users = context.Users.Where(u => u.Popularity == (int)(EF.Functions.Random() * 5.0) + 1).ToList();

This translates to the following SQL when using a SQL Server database:

SELECT [u].[Id], [u].[Popularity], [u].[Username]
FROM [Users] AS [u]
WHERE [u].[Popularity] = (CAST((RAND() * 5.0E0) AS int) + 1)

Support for SQL Server sparse columns

GitHub Issue: #8023.

SQL Server sparse columns are ordinary columns that are optimized to store null values. This can be useful when using TPH inheritance mapping where properties of a rarely used subtype will result in null column values for most rows in the table. For example, consider a ForumModerator class that extends from ForumUser:

    public class ForumUser
    {
        public int Id { get; set; }
        public string Username { get; set; }
    }

    public class ForumModerator : ForumUser
    {
        public string ForumName { get; set; }
    }

There may be millions of users, with only a handful of these being moderators. This means mapping the ForumName as sparse might make sense here. This can now be configured using IsSparse in OnModelCreating. For example:

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder
                .Entity<ForumModerator>()
                .Property(e => e.ForumName)
                .IsSparse();
        }

EF Core migrations will then mark the column as sparse. For example:

CREATE TABLE [ForumUser] (
    [Id] int NOT NULL IDENTITY,
    [Username] nvarchar(max) NULL,
    [Discriminator] nvarchar(max) NOT NULL,
    [ForumName] nvarchar(max) SPARSE NULL,
    CONSTRAINT [PK_ForumUser] PRIMARY KEY ([Id]));

NOTE Sparse columns have limitations. Make sure to read the SQL Server sparse columns documentation to ensure that sparse columns are the right choice for your scenario.

In-memory database: validate required properties are not null

GitHub Issue: #10613. This feature was contributed by @fagnercarvalho.

The EF Core in-memory database will now throw an exception if an attempt is made to save a null value for a property marked as required. For example, consider a User type with a required Username property:

    public class User
    {
        public int Id { get; set; }

        [Required]
        public string Username { get; set; }
    }

Attempting to save an entity with a null Username will result in the following exception:

Microsoft.EntityFrameworkCore.DbUpdateException: Required properties ‘{‘Username’}’ are missing for the instance of entity type ‘User’ with the key value ‘{Id: 1}’.

This validation can be disabled if necessary. For example:

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder
                .LogTo(Console.WriteLine, new[] { InMemoryEventId.ChangesSaved })
                .UseInMemoryDatabase("UserContextWithNullCheckingDisabled")
                .EnableNullabilityCheck(false);
        }

Improved SQL Server translation for IsNullOrWhitespace

GitHub Issue: #22916. This feature was contributed by @Marusyk.

Consider the following query:

        var users = context.Users.Where(
            e => string.IsNullOrWhiteSpace(e.FirstName)
                 || string.IsNullOrWhiteSpace(e.LastName)).ToList();

Before EF Core 6.0, this was translated to the following on SQL Server:

SELECT [u].[Id], [u].[FirstName], [u].[LastName]
FROM [Users] AS [u]
WHERE ([u].[FirstName] IS NULL OR (LTRIM(RTRIM([u].[FirstName])) = N'')) OR ([u].[LastName] IS NULL OR (LTRIM(RTRIM([u].[LastName])) = N''))

This translation has been improved for EF Core 6.0 to:

SELECT [u].[Id], [u].[FirstName], [u].[LastName]
FROM [Users] AS [u]
WHERE ([u].[FirstName] IS NULL OR ([u].[FirstName] = N'')) OR ([u].[LastName] IS NULL OR ([u].[LastName] = N''))

Database comments are scaffolded to code comments

GitHub Issue: #19113. This feature was contributed by @ErikEJ.

Comments on SQL tables and columns are now scaffolded into the entity types created when reverse-engineering an EF Core model from an existing SQL Server database. For example:

/// <summary>
/// The Blog table.
/// </summary>
public partial class Blog
{
    /// <summary>
    /// The primary key.
    /// </summary>
    [Key]
    public int Id { get; set; }
}

Microsoft.Data.Sqlite 6.0 Preview 1

TIP You can run and debug into all the preview 1 samples shown below by downloading the sample code from GitHub.

Savepoints API

GitHub Issue: #20228.

We have been standardizing on a common API for savepoints in ADO.NET providers. Microsoft.Data.Sqlite now supports this API, including:

  • Save to create a savepoint in the transaction
  • Rollback to roll back to a previous savepoint
  • Release to release a savepoint

Using a savepoint allows part of a transaction to be rolled back without rolling back the entire transaction. For example, the code below:

  • Creates a transaction
  • Sends an update to the database
  • Creates a savepoint
  • Sends another update to the database
  • Rolls back to the savepoint previous created
  • Commits the transaction
        using var connection = new SqliteConnection("DataSource=test.db");
        connection.Open();

        using var transaction = connection.BeginTransaction();

        using (var command = connection.CreateCommand())
        {
            command.CommandText = @"UPDATE Users SET Username = 'ajcvickers' WHERE Id = 1";
            command.ExecuteNonQuery();
        }

        transaction.Save("MySavepoint");

        using (var command = connection.CreateCommand())
        {
            command.CommandText = @"UPDATE Users SET Username = 'wfvickers' WHERE Id = 2";
            command.ExecuteNonQuery();
        }

        transaction.Rollback("MySavepoint");

        transaction.Commit();

This will result in the first update being committed to the database, while the second update is not committed since the savepoint was rolled back before committing the transaction.

Command timeout in the connection string

GitHub Issue: #22505. This feature was contributed by @nmichels.

ADO.NET providers support two distinct timeouts:

  • The connection timeout, which determines the maximum time to wait when making a connection to the database.
  • The command timeout, which determines the maximum time to wait for a command to complete executing.

The command timeout can be set from code using <xref:System.Data.Common.DbCommand.CommandTimeout?displayProperty=nameWithType>. Many providers are now also exposing this command timeout in the connection string. Microsoft.Data.Sqlite is following this trend with the Command Timeout connection string keyword. For example, "Command Timeout=60;DataSource=test.db" will use 60 seconds as the default timeout for commands created by the connection.

TIP Sqlite treats Default Timeout as a synonym for Command Timeout and so can be used instead if preferred.

Daily builds

EF Core previews are aligned with .NET 6 previews. These previews tend to lag behind the latest work on EF Core. Consider using the daily builds instead to get the most up-to-date EF Core features and bug fixes.

As with the previews, the daily builds require .NET 5.


The EF Core Community Standup

The EF Core team is now live streaming every other Wednesday at 10am Pacific Time, 1pm Eastern Time, or 17:00 UTC. Join the stream to ask questions about the EF Core topic of your choice, including the latest preview release.

Documentation and Feedback

The starting point for all EF Core documentation is docs.microsoft.com/ef/.

Please file issues found and any other feedback on the dotnet/efcore GitHub repo.

The following short links are provided for easy reference and access.

EF Core Community Standup Playlist: https://aka.ms/efstandups

Main documentation: https://aka.ms/efdocs

Issues and feature requests for EF Core: https://aka.ms/efcorefeedback

Entity Framework Roadmap: https://aka.ms/efroadmap


Thank you from the team

A big thank you from the EF team to everyone who has used EF over the years!

ajcvickers Arthur VickersAndriySvyryd Andriy Svyryd Brice LambsonJeremyLikness Jeremy Likness
maumar Maurycy Markowskiroji Shay Rojanskysmitpatel Smit Patel

Thank you to our contributors!

Ali-YousefiTeloriAndrewKituardalisCaringDev
Ali-YousefiTeloriAndrewKituardalisCaringDev
#1#1#1#1
carlreinkecgrimes01cincuranetdan-giddins
carlreinkecgrimes01cincuranetdan-giddins
#1#1#1#1
dennissedersDickBakerErikEJfagnercarvalho
dennissedersDickBakerErikEJfagnercarvalho
#1, #2, #3, #4, #5, #6#1#1, #2, #3, #4, #5#1
filipnavaragaryngGeoff1900gfoidl
filipnavaragaryngGeoff1900gfoidl
#1#1, #2, #3#1#1
gurustronHSchwichtenbergjantleejoaopgrassi
gurustronHSchwichtenbergjantleejoaopgrassi
#1#1#1#1
josemiltonsampaioKaloyanITkhalidabuhakmehkhellang
josemiltonsampaioKaloyanITkhalidabuhakmehkhellang
#1#1, #2#1, #2#1
koenbeukkotpalleonardoporroMarusyk
koenbeukkotpalleonardoporroMarusyk
#1#1#1#1, #2
MaxG117mefateahmeggimamsawczyn
MaxG117mefateahmeggimamsawczyn
#1#1#1#1
MSDN-WhiteKnightnatashanikolicnmichelsnschonni
MSDN-WhiteKnightnatashanikolicnmichelsnschonni
#1#1#1#1, #2, #3, #4
pkellnerralmsdeveloperRaymondHuyShirasho
pkellnerralmsdeveloperRaymondHuyShirasho
#1#1#1, #2, #3, #4#1
SimonCroppthe-wazztkp1nTomkaa
SimonCroppthe-wazztkp1nTomkaa
#1, #2#1#1#1
umitkavalavincent1405wmeints
umitkavalavincent1405wmeints
#1, #2#1#1

10 comments

Leave a comment

  • Avatar
    Theo Albers

    Hey Jeremy, I’m a little confused about the prerequisites.

    With EFCore 5.0 we run happily on .NET Core 3.1 due to the NS support:
    “…
    EF Core 5.0 requires a .NET Standard 2.1 platform. This means EF Core 5.0 will run on .NET Core 3.1 or .NET 5, as well as other platforms that support .NET Standard 2.1. EF Core 5.0 does not run on .NET Framework.
    …”
    https://devblogs.microsoft.com/dotnet/announcing-the-release-of-ef-core-5-0/

    I guess this implies that running EFCore 6 on .NET Core 3.1 will no longer be an option. I understand that .NET Core 3.1 is LTS (December 3, 2022), .NET 5 isn’t, but .NET 6 will be the next LTS.

    Theo.

      • Avatar
        Ben Hayat

        Hi Jeremy; Thanks for the reply and question;

        Back in 2007 I started with LINQtoSQL, and then EF Version 1 came out. What I loved about EF, vs. dealing directly with ADO.net for data access, was the fact, that as a consumer of data in my app, I was now under the protection and guidance of EF technology to perform data access. Being involved in DB app development since 1982, I’ve had my share of Wild Wild West of data access and all the problems that a developer can run into.
        EF gave us a protective and managed layer to perform data access and that’s why I walked away from ADO.net a long time ago.

        Last year I was forced to use Dapper than EF, and I faced with so many issues, dealing with data management, concurrency and a lot of manual work to perform complex CRUD operation. EF allows me to work on my app, than doing data plumbing.

        When I looked into MongoDB .Net provider, firstly I had to learn a new mindset and worst than that, I had to sort of reinvent my own EF again like I had to do with Dapper.
        So, as long as I’m in MSFT and .Net camp, I much prefer to use EF as my data layer than one-off SDK of MongoDB or other SDK. That’s my answer to your last question. I hope I was clear about my reasoning.
        It’s like, if I plan to vacation a foreign country, I prefer an English speaking country, to make communication easier.