Filtered includes now supported in Entity Framework Core 5.0

Filtered includes is an awesome new feature in Entity Framework Core 5.0 which was released in November 2020.

Without lazy loading (supported but turned off by default in EF Core 2.1+) we need to use the include method to eager load related entities but in Entity Framework Core < 5.0 you couldn’t use filters on the related entities. This meant for example that if you wanted any child posts of a blog you had to load all child posts.. and then filter on the C# side. Obviously depending on the situation this could affect performance. Thankfully the ability to filter the include method is now supported.

In snippet 1 below (click for a larger version in a new window) we can see the LINQ and SQL generated when we include all child posts of each blog. This is all we can do in Entity Framework Core < 5.0 which can result in unneeded data being returned from the DB.

In snippet 2 we can see a sample of the runtime error we’ll get in EF Core < 5.0 when trying to use filtered includes.

And finally in snippet 3 we can see the new functionality in action where we can see a sample query that gets generated in EF Core 5.0 when using filtered includes. In this case the include is filtered to only return child posts which have ‘Entity Framework’ in their title.

Entity Framework Core Filtered Includes
Note – I’ve just used String.Contains as a simple example of a filter above but use this with care as it creates a query that is non-sargable (due to the LIKE having a wildcard at the start) meaning it won’t be able to use an index on the title field if there was one.

Easier immutability with Init only properties in C# 9

C# 9 shipped with .NET 5 in November. One change included is init only properties which allow us to have immutable (non-changeable) classes without some of the downsides associated with pre C# 9 approaches.

As can be seen below in C# 8 we’d typically have getters with no setters which gives us immutability…great.. but it means we need a constructor and we can’t use the more shorthand object initializer (C# 3.0) syntax which many developers prefer.

In C# 9 we can use the init keyword which means we can get rid of the constructor and use shorthand object initialization.

This is a small but nice addition to the language and means developers don’t have to choose between ease of use and immutability.

Links

C# 9 Language Features | On .NET | Channel 9 (msdn.com)

What’s new in C# 9.0 – C# Guide | Microsoft Docs

Running framework-dependent .NET 5.0 apps in Azure App Service before RTM

.NET 5 Release Candidate 1 (of 2) has just dropped. Prior to its full release and availability as a built in runtime stack in Azure App Service if your looking to try it out you can of course deploy your .NET 5.0 apps as self-contained. This means you don’t need the framework installed, this is the beauty of .NET Core after all…

BUT…

If you prefer framework-dependent deployments, perhaps due to their much smaller size and quicker deploy time you can install an extension into your App Service to enable the 5.0 RC1 runtime.

The extension option is available if you navigate to your app service and click Development Tools -> Extensions. Restart your app afterwards.

Using .Net 5 in Azure App Service

Reading Entity Framework Core connection string from appSettings.json

When you run Scoffold-DbCotext with a connection string EF Core will scaffold your DB but will put the hardcoded connection string in the OnConfiguring method of your new DbContext class. If you prefer having Entity Framework Core read the connection from an appSettings file this is easily done. Note the below code works as of EF Core 3.1.7.

If your appSettings has a connection string for ‘BloggingDatabase’…

appSettings config example

You can run Scaffold-DbContext with the Name parameter which points to your connection String name.

Scaffold with named connection

This will cause EF to rebuild your objects and generate an onConfiguring method similar to below..

onconfiguring method

However we can ignore this as we’re going to configure our connection string and any other DbContext related options in the Startup.cs file. Below we setup appSettings.json to be used as our configuration and in the ConfigureServices method we add a DbContext and set its connection string.

Startup.cs registering DBContext

To actually query against the DbContext we’ve added we can inject an instance of it into our controllers constructor. This makes it very clear to other developers that the controller relies on the EFContext class and since Dependency Injection is built into .NET Core is very easy to do.

DbContext Inject

Alternatively rather than injecting specific services we can inject an instance of IServiceProvider and use its GetService method to get an instance of our EFContext class.

Inject IServiceProvider

You might prefer the IServiceProvider approach if your controller has a lot of dependencies. In most cases however I’d recommend injecting specific dependencies as its a little more obvious to other developers what services a controller depends on.

Setting a specific Brotli compression level when using response compression in ASP.NET Core

Brotli can compress HTML, CSS and JS files more than Gzip. If you can’t enable Brotli compression on the server level but want to use it in your ASP.NET Core app you can use the response compression middleware to enable it from your Startup.cs file. Setup is easy and looks like below..

Setting up MVC response compression

Note the app.UseResponseCompression() in the Configure method needs to be before app.UseStaticFiles() as otherwise headers have already been sent. The default setup above will use Brotli if the client supports it else it will use Gzip if it’s supported. By default the Brotli compression provider will be set to a compression level of 1 (fastest).

The compression level corresponds to how aggressive an algorithm will compress a document. Brotli has 11 levels, 1 being the fastest but least compressed and 11 being the most compressed but also the slowest. Brotli at its highest level (11) is extremely slow compared to Gzip at its highest level (9). Slow compression is fine for static CSS/JS files which we can compress ahead of time. For on the fly compression (eg. dynamic web pages) slow speeds can negatively impact web app performance..

SO

.. for Brotli compression to be advantageous over Gzip we need to find the compression level which gives us the best balance between compression amount and speed..

BUT

the problem with the Brotli compression provider in ASP.NET Core is that it only has three options in its enum for setting the level…

ResponseCompression Options

There is no enum option for the best balance between compression and speed. In this case we can just set the level with a number directly…

Setting Brotli Level

You need to experiment with different levels but a number of resources seem to be agreeing on level 4 or 5 as being the sweet spot…

https://blogs.akamai.com/2016/02/understanding-brotlis-potential.html

https://paulcalvano.com/2018-07-25-brotli-compression-how-much-will-it-reduce-your-content

https://quixdb.github.io/squash-benchmark/#results-table

Of course for your static content such as CS, JS, Fonts etc. compress to the max with 11. This will give you significant byte savings over Gzip.