Solution Architect Details What's New in Entity Framework Core 3
Entity Framework Core, Microsoft's object relational mapping (ORM) data access tool, was re-written from the ground up in the shift from the aging, proprietary .NET Framework to the open-source, cross-platform .NET Core. In that process the Microsoft developers took a fresh look at EF, and many features were changed and re-thought, causing it to continue playing catch-up to features added in 10 years of development leading up to EF 6, while also exploring new programming options that have popularized since the original design came out, including non-relational data stores.
To sort all that out, Jim Wooley, a solution architect at Slalom Consulting, this week presented on "What's New in EF Core 3" at the Live! 360 conference in Orlando.
While EF Core 3 has a number of new features, Wooley emphasized the importance of paying attention to breaking changes.
Noting the new features, Wooley told the audience, "there's also a slew of breaking changes. And we want to make sure that we cover a number of these breaking changes, because sometimes these breaking changes may be more critical to you than what the new features are as well."
Wooley demonstrated that by taking some existing v2.2 code and migrating it to v3.0, quickly finding some build errors. "If you have an existing application that started with .NET 1, 2, 2.1, 2.2 wherever in that framework, you're probably going to experience at some point an issue with the code that you've written. And some of these will be caught by the compiler."
One thing to watch out for are changes in data access, and for one example he explained this specifically in the context of the FromSql statement. "So now instead of FromSql, you have two variants. One is FromSql interpolated and the second one is FromSql raw." His demo showed how the new way of using regular strings or interpolated strings -- which are changed into parameters -- can cause problems if not explicitly handled correctly.
"So one of the breaking changes is the FromSql statement that we had. FromSql could either take a regular text string or an interpolated string, and if you gave it an interpolated string, it changed that interpolated string into parameters. But if you gave it a string variable, and you didn't use the interpolated string on the line before for that, and then expected it to use parameters, you wouldn't know that because it's now a string not an interpolated string. Okay, so they wanted you to be very explicit about that." After finding a fixing a couple FromSql and other test errors, Wooley emphasized the importance of integration testing along with unit tests.
In some cases the test errors resulted from "a significant change in mindset between the first versions of .NET Core Entity Framework and Core 3." That change in mindset brought about a change from issuing mulitiple queries in some cases to just one single query.
"There was a significant change in mindset between the first versions of .NET Core Entity Framework and Core 3.
Jim Wooley, Solution Architect, Slalom Consulting
"But you have to make sure that that single query is just the right single query. Otherwise, is it going to give you a compile time, say, 'hey, this might be a problem?' No, it's gonna give you a runtime exception. When's the worst time to find an error -- after you've shipped it, right? Because it's so much more expensive to fix the problem after you ship it than it is to fix it when you're initially developing it. Which is one of the reasons why if you're going to upgrade, I strongly recommend you have a set of integration tests. And in addition to your unit tests, to be able to least catch some of these. If not, have an end-to-end testing or some sort of testing methodology, that's going to make sure that you're not running exceptions."
Wooley advised attendees that they might want to further familiarize themselves with that. "If you've ever profiled, and you saw that you had multiple queries that were issued where you thought was supposed to be a single one, you may or may not be able to run it, and may issue, have a runtime exception, so you may want to take a look at that one and get deeper into it."
Another aspect of the design that changed significantly in 3.0 is that we now always generate a single SQL statement per LINQ query. In previous versions, we used to generate multiple SQL statements in certain cases, like to translate Include() calls on collection navigation properties and to translate queries that followed certain patterns with subqueries. Although this was in some cases convenient, and for Include() it even helped avoid sending redundant data over the wire, the implementation was complex, it resulted in some extremely inefficient behaviors (N+1 queries), and there was situations in which the data returned across multiple queries could be inconsistent.
Other problems might stem from EF Core 3.0 being removed from ASP.NET Core 3.0. As Microsoft announced in September, "EF Core 3.0 is distributed exclusively as a set of NuGet packages." Furthermore, this means that, "When upgrading applications that target older versions of ASP.NET Core to 3.0, you also have to add the EF Core packages as an explicit dependency."
Wooley mentioned that in a demo. "Notice here that I'm not just using the ASP.NET all or ASP.NET Core, I'm actually instancing specifically under the Entity Framework libraries here. One of the breaking changes actually is they have now pulled Entity Framework out of the Core and all from 3.0. So that way, they're able to read that separately from the full ASP.NET stack, okay. So if you have that only is specified in the one side, you're going to need to add that in on the other side as well."
Another change affects tooling, such as design tools. "The other thing is, if you're using the tools, you can install them locally, they're no longer part of the SDK. So you'll have to install those separately. So these tools are going to be for all your scaffolding and migrations in particular. So if you're using any of the CLI tools to be doing those, then you probably want to be making sure that you're pulling those in separately. You can install them globally now, so that you don't have to install them only single to individual project."
A few of the many other things Wooley detailed include:
- EF Core 3 targets .NET Stanard 2.1 instead of v2.0
- Changes in the logging implementation that require less plumbing
- Backing fields are used by default
- CosmosDB support
- C# 8.0 support
In wrapping up, he looked to the future. "Though EF Core 3.1 is under active development, it's projected to ship probably in the next month or so if you want to look at what's going on in three, or even get the bits and try to build them yourself, it's all out there. And so on GitHub, there will be some small performance quality and stability improvements, not really much in terms of feature enhancements. And this is really the LTS support version. And then what's coming along with Core.next is going to be shipping with .NET 5, and they haven't announced any features or anything necessarily going to go in there."
Wooley invited attendees to check out his EF Core demos themselves, available on GitHub.
David Ramel is an editor and writer for Converge360.