With the release of NET 6 I wanted to update the code in the repo called EfCoreinAction-SecondEdition which contains the code that goes with my book “Entity Framework Core in Action 2nd edition”. This code is based on ASP.NET Core 5 and EF Core 5 and this article describes what I had to do to update the NET 5 version of the code to NET 6, plus a look at any performance improvements.
- I updated a non-trivial ASP.NET Core / EF Core application (22 projects) from EF Core 5 to EF Core 6. Overall, it was pretty easy and only took a few days.
- You have to use Visual Studio 2022 (or VSCode) – Visual Studio 2019 doesn’t work
- Any project using ASP.NET Core / EF Core NuGet packages has to have a target framework of net6.0.
- My ASP.NET Core MVC updated with no changes to the code.
- The EF Core parts, which as complex, had two compile errors on unusual parts of EF Core and a few runtime errors, mainly around the Cosmos DB changes.
- I didn’t find any performance improvements, but that’s because my queries were SQL database bound, taking between 10 ms. to 800 ms. to get a result.
In part 3 of my book, I build a complex ASP.NET Core / EF Core application aimed at testing the performance of EF Core. This code is in the Part3 branch and contains 22 projects that use quite of the more intricate parts of EF Core features such as Global Query Filters, user-defined functions, table splitting, transactions and so on. This means any EF Core breaking changes are likely to been seen on this application. My aim was to:
- Convert my book setting web site to NET 6 and get it compile.
- Make the 200 ish xUnit tests to run successfully
- To make the application run
- Test the performance of the updated application
NOTE: I did NOT plan to change the code to use new NET 6 features, such as ASP.NET Core simplified Program class or EF Core features such as the new SQL Server Temporal Tables support or improved Cosmos DB support. That’s for another day.
Overall, the update from EF Core 5 / ASP.NET Core was fairly easy. I didn’t have to change any of the ASP.NET Core project, other than changing its target framework to net6.0 and updating all the NuGet packages. I would say getting the right order for the first four steps weren’t obvious (old articles said I could use Visual Studio 2019, but it can’t).
Here is a step-by-step list to each step, with links to each part
- Download Net6 SDK and Visual Studio 2022
- Update projects that have EF Core / ASP.NET Core packages in them
- Update your NuGet packages to version 6
- Fix any compile errors caused by the version 6 update
- Run your unit tests and fix any changes
- Run the application and check it works
- Did performance improve?
To start, you need to download and install the correct NET 6 SDK for your development machine.
You also need to download Visual Studio 2022, as Visual Studio 2019 doesn’t support Net 6. Then run Visual Studio 2022 and open your application. Visual Studio 2022 does support Visual Studio 2019 solutions so you can run any tests or check your application before you start the upgrade.
TIP: Make a new branch for the changes, as its useful to check back to the older version if something doesn’t work.
To update EF Core to version 6 requires the projects that use EF Core / ASP.NET Core NuGet packages to have a target framework of net6.0. ASP.NET Core tends to be in one single project, but EF Core is likely to be in multiple projects.
Before EF Core 6 came out you could use netstandard2.1 for EF Core 5, or netstandard2.0 for EF Core 3.1 or below. But with EF Core 6 you must update the project’s target framework to net6.0 before you try to update to EF Core 6, otherwise the EF Core 6 NuGet updates will fail.
To update a project in Visual you click on the project which will open the project’s .csproj file. You can then edit the TargetFramework part to Net6.0.
Updating projects to net6.0 has ramifications if you are using any kind of layered architecture, because a project using the netstandard2.1 framework can’t have a project reference to a net6.0 project. In my BookApp I was using a clean architecture approach, so the inner Domain projects (called entities in clean architecture) didn’t contain any EF Core and could use the netstandard2.1 framework, but other than I had to change all the projects to net6.0.
NOTE: This is part of the change over to .NET and going forward you will be using named .NET versions (e.g. net6.0, net7.0) much more in the lower layers in your applications.
Once your packages are changed net6.0, then you can use the “Manage NuGet Packages for Solutions”, by right-clicking on the “Solution” at the top of the Solution Explorer. When you are in the NuGet Package Manager select the “Updates” tab which should provide a list of NuGet packages already installed in your application, which suggestions for newer NuGet versions.
As well as EF Core upgrades there may be other NuGet packages you use, such as open-source libraries that you find useful. Be a little careful of libraries that use EF Core inside, as some of them might work. For instance, I have about ten libraries that work with .NET and four of them needed to be updated, but the rest were OK. I didn’t find that until I tried to use them, so check any code that uses an external library that haven’t said it works with net 6 – a lot will work, but some might not.
You shouldn’t find many breaking changes that causes a compile error, but I did have two, but they are unusual parts of EF Core.
- One was a change in the IModelCacheKeyFactory signature – I had to add a new parameter
- Another was around the use of EF Core’s FromSqlRaw method. Because my app works with both SQL Server and Cosmos DB database types I got a compile time error CS0121, “The call is ambiguous between the following methods or properties” (see EF Core issue #26503), which I fixed.
When I ran my xUnit tests and out of 200 tests, of which the majority are integration tests using EF Core, and I had only a few errors. The biggest was around the changes in EF Core 6’s improvements of handling Cosmos DB.
- There was a change to the configuration of collections of owned types, which I needed for my Cosmos DB code. This has changed (for the better) in EF Core 6.
- The whole handing of Cosmos DB create / update / delete exceptions had been improved, so I had to change that code.
- I had some problems when using FromSqlRaw method with Cosmos DB. That’s because there are big improvements to Cosmos DB support in EF Core 6. I fixed the Cosmos DB code, but I didn’t upgrade my code to use the new features because it’s a lot of work. I hope to look at this later.
- The last test that failed was checking for a bug in EF Core 5 (see EF Core issue #22701) which I was checking for so I would know when it was fixed. I’m glad to see that bug was fixed, and I removed the unit test that was there to alert a change.
NOTE: If you want to test code that uses EF Core, I suggest you look at my library EfCore.TestSupport. This has a lot of useful features that speeds up the writing of tests that need access to your application’s DbContext. Also, my book “Entity Framework Core in Action” has a whole chapter about testing code that uses EF Core.
xUnit tests are great, but there are lots of things that are hard to test, especially some of ASP.NET Core features. The only problem I found was my analysis code relied on logging data, and ASP.NET Core had changed its name / event code. I didn’t test every minor point but I did some detailed performances tests and I didn’t find any other problems.
EF Core 6 has a lot of work done to reduce the overheads of converting LINQ to SQL and they know it has improved the performance and I was interested to see if it made any effect to the a web site for selling book that I created in chapters 15 and 16 (see this EF Core Community Standup video where I cover performance tuning).
I retested my performance tests with EF Core 6, and I didn’t find any improvements. Thinking about it I realised my performance tests took between 10 ms. to 800 ms. of database access time, which means any improvements to the code overhead wouldn’t make any effect. I did try small queries taking 1 to 3 ms. and there was possibly an improvement, but because the logging only works in 1 ms. steps I wasn’t able to be sure.
So, my takeaway is that reducing the overheads EF Core code is a good thing, but don’t expect EF Core 6 to suddenly improve your really slow database accesses.
Overall, updating my book selling web app to net6.0 took a few days, which I think is quite good. I did waste time trying to use Visual Studio 2019 to work with net6.0 because of old articles said it did support net6.0, which isn’t true now – need Visual Studio 2022. I also found (the hard way) I had to update the projects to net6.0 before I could load the new net6 NuGet packages.
My integration tests were wonderful as they pointed out the parts that didn’t work, especially with the large changes/improvements to Cosmos DB. Finding those issues would have very difficult using manual testing because they are only triggered in errors states, which is difficult to do manually.
I’m also really pleased with the improvements such as SQL Server temporal tables, migration bundles, global model config and of course the better support of Cosmos DB (see “what new in EF Core 6” for the full list). I look forward to using EF Core 6 in my future applications.