.NET Reunified : Announcing .NET 5.0 š
And how to migrate.
On November 10th 2020, Microsoft announced .NET 5.0, marking an important step forward for developers working across desktop, Web, mobile, cloud and device platforms. In fact, .NET 5 is that rare platform update that unifies divergent frameworks, reduces code complexity and significantly advances cross-platform reach. NET 5.0 is already battle-tested by being hosted for months at dot.net and Bing.com (version).
What & Why
With this release (of course after on preview for around an year) they merged the source code streams of several key frameworks ā .NET Framework, .NET Core and Xamarin/Mono. The effort was to even unify threads that separated at inception at the turn of the century, and provide developers one target framework for their work.
Mark Michaelis on MSDN Magazine said ā The two frameworks began to look more and more alike because of the standard. As the APIs became more consistent, the obvious question began to arise: Why not move the separate code bases back together? And, in fact, starting with .NET Core 3.0 preview, so much of the .NET Framework WPF and Windows API was cherry-picked and merged into the .NET Core 3.0 code base, that this is exactly what happened. The source code for .NET Core 3.0 became one and the same with the modern day (desktop, cloud, mobile and IoT) functionality in .NET Framework 4.8. ā
There are many important improvements in .NET 5.0:
- Performance is greatly improved across many components and is described in detail at Performance Improvements in .NET 5.0, Arm64 Performance in .NET 5.0, and gRPC.
- C# 9 and F# 5 offer new language improvements such as top-level programs and records for C# 9, while F# 5 offers interactive programming and a performance boost for functional programming on .NET.
- .NET libraries have enhanced performance for Json serialization, regular expressions, and HTTP (HTTP 1.1, HTTP/2). They are also are now completely annotated for nullability.
- P95 latency has dropped due to refinements in the GC, tiered compilation, and other areas.
- Application deployment options are better, with ClickOnce client app publishing, single-file apps, reduced container image size, and the addition of Server Core container images.
- Platform scope expanded with Windows Arm64 and WebAssembly.
Performance!
For anyone interested in .NET and performance, garbage collection is frequently top of mind. Lots of effort goes into reducing allocation, not because the act of allocating is itself particularly expensive, but because of the follow-on costs in cleaning up after those allocations via the garbage collector (GC). No matter how much work goes into reducing allocations, however, the vast majority of workloads will incur them, and thus itās important to continually push the boundaries of what the GC is able to accomplish, and how quickly.
This release has seen a lot of effort go into improving the GC. For example,
- dotnet/coreclr#25986 implements a form of work stealing for the āmarkā phase of the GC
- dotnet/runtime#35896 optimizes decommits on the āephemeralā segment (gen0 and gen1 are referred to as āephemeralā because theyāre objects expected to last for only a short time). Decommitting is the act of giving pages of memory back to the operating system at the end of segments after the last live object on that segment.
- dotnet/runtime#32795, which improves the GCās scalability on machines with higher core counts by reducing lock contention involved in the GCās scanning of statics.
- dotnet/runtime#37894, which avoids costly memory resets (essentially telling the OS that the relevant memory is no longer interesting) unless the GC sees itās in a low-memory situation.
- dotnet/coreclr#27729, which reduces the time it takes for the GC to suspend threads, something thatās necessary in order for it to get a stable view so that it can accurately determine which are being used.
Not only GC, NET 5 is an exciting version for the Just-In-Time (JIT) compiler, too, with many improvements of all manner finding their way into the release. In .NET Core 3.0, over a thousand new hardware intrinsics methods were added and recognized by the JIT to enable C# code to directly target instruction sets like SSE4 and AVX2 (see the docs). These were then used to great benefit in a bunch of APIs in the core libraries. However, the intrinsics were limited to x86/x64 architectures. In .NET 5, a ton of effort has gone into adding thousands more, specific to ARM64. Text processing helpers like System.Char
received some nice improvements in .NET 5. For example, dotnet/coreclr#26848 improved the performance of char.IsWhiteSpace
by tweaking the implementation to require fewer instructions and less branching, also, not to mention the System.Text.RegularExpressions which has received myriad of performance improvements.
C# 9
C# 9.0 adds the following features and enhancements to the C# language:
- Records
- Init only setters
- Top-level statements
- Pattern matching enhancements
- Native sized integers
- Function pointers
- Suppress emitting localsinit flag
- Target-typed new expressions
- static anonymous functions
- Target-typed conditional expressions
- Covariant return types
- Extension
GetEnumerator
support forforeach
loops - Lambda discard parameters
- Attributes on local functions
- Module initializers
- New features for partial methods
As an example, take a look at Top-level statements. Top-level statements remove unnecessary ceremony from many applications. Consider the canonical āHello World!ā program:
Thereās only one line of code that does anything. With top-level statements, you can replace all that boilerplate with the using
statement and the single line that does the work:
If you wanted a one-line program, you could remove the using
directive and use the fully qualified type name:
System.Console.WriteLine("Hello World!");
Eat that Python!
EF Core 5.0
The foundation from 3.1 enabled the Microsoft 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:
- Over 230 enhancements
- Over 380 bug fixes
- Over 80 cleanup and API documentation updates
- Over 120 updates to documentation pages
As an example, In EF Core up to and including 3.x, it is necessary to include an entity in the model to represent the join table when creating Many-to-many relationship mapping, and then add navigation properties to either side of the many-to-many relations that point to the join entity instead:
And then in the Db context,
But with EF Core 5.0, you can do,
When Migrations (or EnsureCreated
) are used to create the database, EF Core will automatically create the join table.
Migrate from .NET Core 3.1 to .NET 5.0
Take a look here to see what are the breaking changes in .NET 5.0
I will start with an eample project I created a while back for my .NET Core Authentication From Scratch series.
We will start with the source code of the same project, the technology stack of the projects is as follows.
- Asp.Net Core 3.1 Web API
- Entity Framework Core 3.1 (Code First)
- SQL Server Database
Before we do anything, if youāre using Visual Studio, you need to update it to version 16.8, If youāre using .NET Core CLI, you need to download .NET 5.0 SDK from here.
After updating and restarting your PC, try to create a new .NET Core Web Application. If everything was installed properly, you will be able to select .NET Core 5.0 option.
In either case if you open up a command prompt and execute dotnet --info
you should see .NET 5.0 SDK listed.
You also might want to update dotnet-ef
tool as well (Entity Framework Core .NET Command-line Tools) to version 5.0. Check for your version by executing dotnet ef
in cmd
. If itās not 5.0, update it using following command.
dotnet tool update --global dotnet-ef --version 5.0.0
Letās open our project from VSCode or any other text editor. We need to update few things in the .csproj
file. (If youāre using Visual Studio open up the .csproj
file by right click
on the project ā > Edit project file
.
Cool. Now, edit the <TargetFramework>
from netcoreapp3.1
to net5.0
<TargetFramework>net5.0</TargetFramework>
And for other <PackageReference/>
items should be updated to the latest version. Specially the packages start with Microsoft.AspNetCore
and Microsoft.EntityFrameworkCore
. As an eample Microsoft.AspNetCore.Authentication.JwtBearer
should have Version="5.0.0"
. Make sure to update other 3rd party packages also to the latest version if you find something not working properly. Just search it in the nuget gallery and get the version. https://www.nuget.org/packages
My csproj
before updating.
My csproj
after updating.
Now, open up a terminal and execute dotnet restore
to update the packages.
Thatās it, now you should be able to run the project as usual. Updated project is available here.
Conclusion
Weāll wait and see what more things are there to come with new updates. Migrating should be a flawless process, not like migrating from .NET Core 2.1 to 3.0, remember those days? You might run into some other issues, but hey, the whole community is migrating as we speak, there should be fix for whatever problems you face.
Take look at Microsoft docs too.
Happy coding! Stay safe!