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.
Package | Purpose |
---|---|
Microsoft.EntityFrameworkCore | The main EF Core package that is independent of specific database providers |
Microsoft.EntityFrameworkCore.SqlServer | Database provider for Microsoft SQL Server and SQL Azure |
Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite | SQL Server support for spatial types |
Microsoft.EntityFrameworkCore.Sqlite | Database provider for SQLite that includes the native binary for the database engine |
Microsoft.EntityFrameworkCore.Sqlite.Core | Database provider for SQLite without a packaged native binary |
Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite | SQLite support for spatial types |
Microsoft.EntityFrameworkCore.Cosmos | Database provider for Azure Cosmos DB |
Microsoft.EntityFrameworkCore.InMemory | The in-memory database provider |
Microsoft.EntityFrameworkCore.Tools | EF Core PowerShell commands for the Visual Studio Package Manager Console; use this to integrate tools like scaffolding and migrations with Visual Studio |
Microsoft.EntityFrameworkCore.Design | Shared design-time components for EF Core tools |
Microsoft.EntityFrameworkCore.Proxies | Lazy-loading and change-tracking proxies |
Microsoft.EntityFrameworkCore.Abstractions | Decoupled EF Core abstractions; use this for features like extended data annotations defined by EF Core |
Microsoft.EntityFrameworkCore.Relational | Shared EF Core components for relational database providers |
Microsoft.EntityFrameworkCore.Analyzers | C# 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 transactionRollback
to roll back to a previous savepointRelease
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 forCommand 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.
- Watch our YouTube playlist of previous shows
- Visit the .NET Community Standup page to preview upcoming shows
- Suggest a guest or project, including your own by commenting on the linked issue
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.
Helpful Short Links
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!
Arthur Vickers | Andriy Svyryd | Brice Lambson | Jeremy Likness |
Maurycy Markowski | Shay Rojansky | Smit Patel |
wo wo wo go go go study study study😍
As excited as you are with the jumble puzzle solver I also want to embed these codes on some of the custom project mine.
Jeremy, any plans to cover MongoDB with EF6? As you guys already covering NoSQL with CosmoDB.
Hi Ben! A MongoDB provider is not in scope for EF Core 6. We do plan to focus on improvements to the Azure Cosmos DB provider. What capabilities in EF Core are you looking to use that aren’t provided with the .NET MongoDB SDK?
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...
I meant EF Core 6.
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...
Hi, Theo. What are you confused about? Your statements are correct: EF Core 6.0 will run on .NET 5 or later and is aligned with .NET 6 in terms of LTS.
Jeremy
How about bulk updates in the database without loading to memory?
Deletes as well. Currently doing this using the .Remove(new Thing { Id = id }) trick, but some actual support would be great.