Let's directly dive in:
?? Compiled Models
With .NET 5 Microsoft introduced Source Generators:
A Source Generator is a piece of code that runs during compilation and can inspect your program to produce additional files that are compiled together with the rest of your code.
A Source Generator is a new kind of component that C# developers can write that lets you do two major things:
- Retrieve a Compilation object that represents all user code that is being compiled. This object can be inspected and you can write code that works with the syntax and semantic models for the code being compiled, just like with analyzers today.
- Generate C# source files that can be added to a Compilation object during the course of compilation. In other words, you can provide additional source code as input to a compilation while the code is being compiled.""
With that we have the option to create C# classes / objects at compile time depending on the current source code. This makes much sense for scenarios like IoT/DI or also
DbContext. Microsoft says it can boost up to 10x faster initial startup time when using Compiled Models.
But those models have strings attached:
- Global query filters are not supported.
- Lazy loading proxies are not supported.
- Change tracking proxies are not supported.
- Custom IModelCacheKeyFactory implementations are not supported.
- The model must be manually synchronized by regenerating it any time the model definition or configuration change.
If you want to know more or even want to try it out, check here
Entity Framework Core 6.0 Preview 4: Performance Edition
Microsoft wants to come as close to Dapper as possible. Thanks to general improvements in .NET 6 and EF 6.0 they improved quite significantly:
- 70% faster on the industry-standard TechEmpower Fortunes benchmark, compared to 5.0
- This is the full-stack perf improvement, including improvements in the benchmark code, the .NET runtime, etc. EF Core 6.0 itself is 31% faster executing queries.
- Heap allocations have been reduced by 43%.
BUT these numbers have to be taken with a grain of salt because of the following quote:
A final, general note on performance. The numbers and improvements reported in this article are for a very specific scenario (TechEmpower Fortunes), using non-tracking queries only (no change tracking, no updates); the benchmarks were executed on a high-performance, low-latency setup. Real-world application scenarios will most probably show very different results, as the runtime overhead of executing queries would be dominated by network or database I/O times.
Allow multiple SQL-Queries in one go to the database. So you save a lot of roundtrip. See more information here The API would be used like this:
using var batch = dbProviderFactory.CreateBatch(); var cmd1 = dbProviderFactory.CreateBatchCommand(); cmd1.CommandText = "UPDATE table SET f1=@p1 WHERE f2=@p2"; var p1 = dbProviderFactory.CreateParameter(); var p2 = dbProviderFactory.CreateParameter(); p1.Value = 8; p2.Value = 9; cmd1.Parameters.Add(p1); cmd1.Parameters.Add(p2); batch.Add(cmd1); var cmd2 = dbProviderFactory.CreateBatchCommand(); cmd2.CommandText = "SELECT * FROM table WHERE f2=@p3"; var p3 = dbProviderFactory.CreateParameter(); p3.Value = 8; cmd2.Parameters.Add(p3); batch.Add(cmd2); batch.Connection = conn; batch.Transaction = transaction; using var reader = batch.ExecuteReader(); // read contains one resultset, from SELECT
You get two main advantages from that:
- Only one time overhead for sending and getting packages to and from the database
- You don't have to wait for query 1 to be completed to send query 2
Unfortunately it doesn't look like this feature will make it in time into EF Core 6.0.
Other smaller improvements
If you have a SQL Database with a
decimal column with specific precision and scale you have to defined the column as custom type like this:
builder.Property(m => m.MyDecimalProperty).HasColumnType("decimal(3,2)");
Now you can directly adjust the precision and scale via [Attribute])https://bloglinkdotnet.azurewebsites.net/blogPost/1a5d039b-d85c-4a16-a64a-cce5281ff1f8). The same applies for
Preserve synchronization context in SaveChangesAsync
If you are not familiar with synchronization context or ConfigureAwait have a look at my earlier post: here.
In short the synchronization context saves the current environment where your code is running. If you await an async call and come back it enforces that you are back were you started. With
ConfigureAwait(false) you basically say, I don't care who is resuming the rest of my async call.
EF Core 5.0 used
ConfigureAwait(false) almost everywhere. But
SaveChangesAsync has a special behavior as it modifies tracked entities. These then can trigger notifications in an UI thread, which would fail. Here more.
If you want to have an overview over all the features and there current status you can check out the EF Core 6 site from Microsoft