Today, the Entity Framework team is delighted to announce the release of EF Core 5.0. This is a general availability/release to manufacturing (GA/RTM) release that addresses final bugs identified in the previous release candidates and is ready for production. EF Core 5.0 is released simultaneously with .NET 5.0.
What’s new in EF Core 5.0
The early releases of EF Core focused on building a flexible and extensible architecture. In EF Core 3.1, the team buttoned down this architecture with some breaking changes and an overhauled query pipeline. The foundation from 3.1 enabled the team and community to deliver an astonishing set of new features for EF Core 5.0. Some of the highlights from the 81 significant enhancements include:
- Many-to-many relationship mapping
- Table-per-type inheritance mapping
- IndexAttribute to map indexes without the fluent API
- Database collations
- Filtered Include
- Simple logging
- Exclude tables from migrations
- Split queries for related collections
- Event counters
- SaveChanges interception and events
- Required 1:1 dependents
- Migrations scripts with transactions
- Rebuild SQLite tables as needed in migrations
- Mapping for table-valued functions
- DbContextFactory support for dependency injection
- ChangeTracker.Clear to stop tracking all entities
- Improved Cosmos configuration
- Change-tracking proxies
- Property bags
These new features are part of a larger pool of changes:
- Almost 240 enhancements
- Over 380 bug fixes
- Over 80 cleanup and API documentation updates
- Over 120 updates to documentation pages
What the community is saying
With so much goodness in EF Core 5.0 it was hard to decide what to cover in the announcement blog post! The team reached out to four pillars of the EF Core community and asked them to weigh in with their favorite features in EF Core 5.0. Here’s what they had to say.
📅 Mark your calendar On Wednesday, November 18th at 10am Pacific Time, the EF Core team will host a special edition of the EF Core Community Standup. Our special guests from the EF Core community will join a live panel discussion about the latest features. Join us and have your EF Core 5.0 questions answered! Details will be posted to the .NET Live page.
Julie Lerman: Simple logging
Julie Lerman is a software coach, Pluralsight author and longtime user of Entity Framework.
EF Core has always integrated with the Microsoft.Extensions.Logging infrastructure. This form of logging is powerful and extensible, but requires external dependencies and configuration. EF Core 5.0 introduces the LogTo method as a simple way to obtain logs while developing and debugging without installing additional dependencies.
LogTo
is called when configuring a DbContext instance. This configuration is commonly done in an override of DbContext.OnConfiguring
. For example:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.EnableSensitiveDataLogging()
.EnableDetailedErrors()
.LogTo(Console.WriteLine);
Alternately, LogTo can be called as part of AddDbContext
or when creating a DbContextOptions
instance to pass to the DbContext
constructor. For example:
serviceCollection.AddDbContext<SomeDbContext>(
b => b.UseSqlServer(Your.ConnectionString)
.EnableSensitiveDataLogging()
.EnableDetailedErrors()
.LogTo(Console.WriteLine));
Both examples set up logging to the console and also turn on sensitive data logging and detailed errors for the best debugging experience. This results in log output to console; for example:
warn: 11/4/2020 12:59:56.097 CoreEventId.SensitiveDataLoggingEnabledWarning[10400] (Microsoft.EntityFrameworkCore.Infrastructure)
Sensitive data logging is enabled. Log entries and exception messages may include sensitive application data; this mode should only be enabled during development.
info: 11/4/2020 12:59:56.190 CoreEventId.ContextInitialized[10403] (Microsoft.EntityFrameworkCore.Infrastructure)
Entity Framework Core 5.0.0-rc.2.20475.6 initialized 'SomeDbContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: SensitiveDataLoggingEnabled
dbug: 11/4/2020 12:59:56.221 RelationalEventId.ConnectionOpening[20000] (Microsoft.EntityFrameworkCore.Database.Connection)
Opening connection to database 'Test' on server '(local)'.
See the simple logging documentation for more information on:
- Logging to the debug window or a file
- Log filtering
- Message contents and formatting
“It’s a beautiful blend of the simplicity of logging in EF6 and the intelligence of .NET Core logging functionality.” — Julie
Diego Vega: Many-to-many (M2M) relationships
Diego Vega is a principal software engineer at Microsoft on the Azure networking team. He formerly served as program manager for the EF Core team.
EF Core 5.0 supports many-to-many relationships without explicitly mapping the join table.
For example, consider these entity types:
public class Post
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Tag> Tags { get; set; }
}
public class Tag
{
public int Id { get; set; }
public string Text { get; set; }
public ICollection<Post> Posts { get; set; }
}
Notice that Post
contains a collection of Tags
, and Tag
contains a collection of Posts
. EF Core 5.0 recognizes this as a many-to-many relationship by convention. This means no code is required in OnModelCreating
:
public class BlogContext : DbContext
{
public DbSet<Post> Posts { get; set; }
public DbSet<Blog> Blogs { get; set; }
}
When Migrations (or EnsureCreated
) are used to create the database, EF Core will automatically create the join table. For example, on SQL Server for this model, EF Core generates:
CREATE TABLE [Posts] (
[Id] int NOT NULL IDENTITY,
[Name] nvarchar(max) NULL,
CONSTRAINT [PK_Posts] PRIMARY KEY ([Id]));
CREATE TABLE [Tags] (
[Id] int NOT NULL IDENTITY,
[Text] nvarchar(max) NULL,
CONSTRAINT [PK_Tags] PRIMARY KEY ([Id]));
CREATE TABLE [PostTag] (
[PostsId] int NOT NULL,
[TagsId] int NOT NULL,
CONSTRAINT [PK_PostTag] PRIMARY KEY ([PostsId], [TagsId]),
CONSTRAINT [FK_PostTag_Posts_PostsId] FOREIGN KEY ([PostsId]) REFERENCES [Posts] ([Id]) ON DELETE CASCADE,
CONSTRAINT [FK_PostTag_Tags_TagsId] FOREIGN KEY ([TagsId]) REFERENCES [Tags] ([Id]) ON DELETE CASCADE);
CREATE INDEX [IX_PostTag_TagsId] ON [PostTag] ([TagsId]);
Creating and associating Blog
and Post
entities results in join table updates happening automatically. For example:
var beginnerTag = new Tag {Text = "Beginner"};
var advancedTag = new Tag {Text = "Advanced"};
var efCoreTag = new Tag {Text = "EF Core"};
context.AddRange(
new Post {Name = "EF Core 101", Tags = new List<Tag> {beginnerTag, efCoreTag}},
new Post {Name = "Writing an EF database provider", Tags = new List<Tag> {advancedTag, efCoreTag}},
new Post {Name = "Savepoints in EF Core", Tags = new List<Tag> {beginnerTag, efCoreTag}});
context.SaveChanges();
After inserting the Posts and Tags, EF will then automatically create rows in the join table. For example, on SQL Server:
Executed DbCommand (8ms) [Parameters=[@p6='1', @p7='1', @p8='1', @p9='2', @p10='2', @p11='2', @p12='2', @p13='3', @p14='3', @p15='1', @p16='3', @p17='2'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
INSERT INTO [PostTag] ([PostsId], [TagsId])
VALUES (@p6, @p7),
(@p8, @p9),
(@p10, @p11),
(@p12, @p13),
(@p14, @p15),
(@p16, @p17);
For queries, Include
and other query operations work just like for any other relationship. For example:
foreach (var post in context.Posts.Include(e => e.Tags))
{
Console.Write($"Post "{post.Name}" has tags");
foreach (var tag in post.Tags)
{
Console.Write($" '{tag.Text}'");
}
}
The SQL generated uses the join table automatically to bring back all related Tags:
SELECT [p].[Id], [p].[Name], [t0].[PostsId], [t0].[TagsId], [t0].[Id], [t0].[Text]
FROM [Posts] AS [p]
LEFT JOIN (
SELECT [p0].[PostsId], [p0].[TagsId], [t].[Id], [t].[Text]
FROM [PostTag] AS [p0]
INNER JOIN [Tags] AS [t] ON [p0].[TagsId] = [t].[Id]
) AS [t0] ON [p].[Id] = [t0].[PostsId]
ORDER BY [p].[Id], [t0].[PostsId], [t0].[TagsId], [t0].[Id]
Unlike EF6, EF Core allows full customization of the join table. For example, the code below configures a many-to-many relationship that also has navigations to the join entity, and in which the join entity contains a payload property:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Post>()
.HasMany(p => p.Tags)
.WithMany(p => p.Posts)
.UsingEntity<PostTag>(
j => j.HasOne(pt => pt.Tag).WithMany().HasForeignKey(pt => pt.TagId),
j => j.HasOne(pt => pt.Post).WithMany().HasForeignKey(pt => pt.PostId),
j =>
{
j.Property(pt => pt.PublicationDate).HasDefaultValueSql("CURRENT_TIMESTAMP");
j.HasKey(t => new { t.PostId, t.TagId });
});
}
See configuring many-to-many relationships to learn more about more complex mappings like this.
“I choose many-to-many because it comes with a payload of additional features.” — Diego
Jon P Smith: ChangeTracker.Clear()
Jon P Smith is a .NET Core backend developer, architect, and the author of Entity Framework Core in Action.
As with all EF Core releases, the team implements big features, but also many smaller usability improvements. The new DbContext.ChangeTracker.Clear()
method is one of these improvements. It clears the EF change tracker so that all currently tracked entities are detached. For example:
using (var context = new BlogContext())
{
// A normal tracking query brings entities into the context
var postsAndTags = context.Posts.Include(e => e.Tags).ToList();
Debug.Assert(context.ChangeTracker.Entries().Count() == 12);
// These can then used for one or more updates
postsAndTags.First().Name = "EF Core 102";
context.SaveChanges();
Debug.Assert(context.ChangeTracker.Entries().Count() == 12);
// All tracked entities can then be detached
context.ChangeTracker.Clear();
Debug.Assert(context.ChangeTracker.Entries().Count() == 0);
}
Note that calling ChangeTracker.Clear()
in this example should usually not be needed when using the best practice of creating a new, short-lived context instance for each unit-of-work. However, sometimes application architecture can make it hard to use a new DbContext
for each unit-of-work. For these case, using ChangeTracker.Clear()
is more performant and robust than mass-detaching all entities.
“My favorite EF Core 5 feature is
ChangeTracker.Clear()
. I use this in my unit tests to clear out any database setup entity classes so that when I run my tests I know it’s read new data from the database.” — Jon
Erik Ejlskov Jensen: Improved database-first scaffolding
Erik Ejlskov Jensen is a Tech Lead at VENZO_nxt and maintains the popular EF Core Power Tools that provides reverse engineering, migrations, and model visualization for EF Core.
EF Core 5.0 includes many improvements for scaffolding (a.k.a. reverse-engineering) a DbContext
for a database-first experience. These are features that can be both used from the command-line tools that ship with EF, or with community projects like Erik’s visual EF Core Power Tools. The following sections show some examples.
Scaffold to custom namespaces
EFCore 5.0 supports overriding the namespace for all scaffolded classes. In addition, if desired, a different namespace can be configured for the DbContext
class. For example:
dotnet ef dbcontext scaffold ... --namespace Your.Namespace --context-namespace Your.DbContext.Namespace
💡 TIP We are showing the .NET command line tool here, but the same options are available in the Package Manager Console PowerShell commands.
Stop scaffolding the connection string
By default, EF Core includes the connection string for the scaffolded database in a call to OnConfiguring
on the generated DbContext
. However, this can be frustrating for applications that already configure the DbContext
in some other way; for example, inside AddDbContext
in an ASP.NET Core application. EF Core 5.0 supports scaffolding a DbContext
without including a call to OnConfiguring
. For example:
dotnet ef dbcontext scaffold ... --no-onconfiguring
Pluralization
EF Core now integrates with Humanizer to provide pluralization by default when scaffolding from a database. Putting all this together, here’s an example command using custom namespaces, no OnConfiguring
, and the default pluralization support:
dotnet ef dbcontext scaffold 'Server=(local);Database=Blogs;User Id=arthur;Password=Unicorns4All'
Microsoft.EntityFrameworkCore.SqlServer --namespace Blogs.Entities
--context-namespace Blogs.Context --no-onconfiguring --data-annotations
This results in the following classes being generated:
#nullable disable
namespace Blogs.Context
{
public partial class BlogsContext : DbContext
{
public BlogsContext()
{
}
public BlogsContext(DbContextOptions<BlogsContext> options)
: base(options)
{
}
public virtual DbSet<Blog> Blogs { get; set; }
public virtual DbSet<Post> Posts { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
}
#nullable disable
namespace Blogs.Entities
{
[Index(nameof(BlogId), Name = "IX_Posts_BlogId")]
public partial class Post
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int? BlogId { get; set; }
[ForeignKey(nameof(BlogId))]
[InverseProperty("Posts")]
public virtual Blog Blog { get; set; }
}
}
#nullable disable
namespace Blogs.Entities
{
public partial class Blog
{
public Blog()
{
Posts = new HashSet<Post>();
}
[Key]
public int Id { get; set; }
public string Name { get; set; }
[InverseProperty(nameof(Post.Blog))]
public virtual ICollection<Post> Posts { get; set; }
}
}
Notice that:
DbSet
property names are pluralized- The entity types are in one namespace and the
DbContext
is in another - There is no
OnConfiguring
method containing my connection string - The new
IndexAttribute
is used instead of generating code inOnModelCreating
#nullable disable
is generated since EF Core does not currently reverse-engineer to nullable reference types
See the documentation for reverse-engineering for more information.
“The many small feature additions to database first scaffolding are amongst my favorite features in EF Core 5: Namespace, no connection string on generated code, pluralization – all features that help improve EF Core Power Tools as well” — Erik
Learn more
There are many good sources of information about EF Core.
- The official documentation contains everything from getting-started guides to advanced feature documentation
- Keep up with the latest changes in the EF Core weekly updates
- The team live streams a community standup every few weeks, including guests, news, and demos
- Ask questions on GitHub or Stack Overflow
- There are many great books, online courses, and blog posts about EF Core out there from the likes of Julie, Jon, Erik, and many others. (If you find something really good, then let us know and we’ll feature it on the community standup.)
Or contact the team for any reason on GitHub or Twitter.
How to get EF Core 5.0
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.
EF Core 5.0 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 5.0.0
This following table links to the release 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.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 |
Installing the EF Core Command Line Interface (CLI)
As with EF Core 3.0 and 3.1, the EF Core 5.0 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 5.0 tool globally the first time, use:
dotnet tool install --global dotnet-ef --version 5.0.0
If you already have the tool installed, update it with:
dotnet tool update --global dotnet-ef --version 5.0.0
It’s possible to use this new version of the EF Core CLI with projects that use older versions of the EF Core runtime.
Special thanks
Development on EF Core is lead by a small team at Microsoft. However, many members of the community contributed to EF Core 5.0, either with code, documentation, or both. Many thanks from the team to everybody who helped us deliver this release!
View the full list of contributors
In addition, a special thank you this release to Diego Vega, our former program manager, who has been fundamental to the design and direction of EF Core over the years. In particular, Diego was a major contributor to the overall design for extensible many-to-many relationships.
Conclusion
Finally, a big thank you to the entire EF community for feedback, support, and bug reports, not to mention the occasional rant! Start using EF Core 5.0 now and continue filing bugs, voting on issues, and letting us know what you need from EF Core.
Thank you,
The EF Core Team
Arthur Vickers | Andriy Svyryd | Brice Lambson | Jeremy Likness |
Maurycy Markowski | Shay Rojansky | Smit Patel |
Hi,
Quick question…why does it say EF 5.0 is supported until Feb 2022 but EF 3.1 supported until Dec 2022, should 5.0 not have a later support date than 3.1?
Thanks.
EF Core follows the same support cycle as .NET Core. The 3.1 release is LTS (long term support) so the support lasts longer. EF Core 6.0 will be the next LTS release.
I’m looking for a discussion of how EF Core might work with C# 9.0 “record” types.
There would seem to be a natural synergy, but I have yet to find a discussion of the topic.
Thanks!
Something is wrong. Why is NuGet offering me version 5.0 in my .NET Framework projects when it isn’t compatible? Is there a way to prevent that? Are you going to continue patching 3.x?
Not sure why NuGet is making those suggestions. 3.1 support will follow the same lifecycle as .NET Core 3.1.
So, I pretty much axed EF Core from my projects since you made it unusable for .NET Framework. Now I see that even Entity Framework requires .NET Standard 2.1. So, in other words, you can’t even have a library that uses Entity Framework shared between a .NET 5 console application and a ASP.NET Web Forms application. Absolutely ridiculous.
So, it looks like it will be supported until 12/3/22. Any idea when .NET Framework 4.8 support ends?
In the linked URL for Over 230 enhancements, you misspelled enhancements. That’s why when you click on the link it can’t find them.
Thanks for the catch! It is fixed now.