In Entity Framework Core (2.2+) if you’re capturing queries in logs consider using the TagWith feature to output an arbitrary comment along with your queries. This can be helpful for identifying where in the code a particular query is executed from or to otherwise provide some context which will be helpful when scrolling through the logs.
Usage is simple, for example, the following query…
Without lazy loading in Entity Framework Core we must eagerly load related entities which means we can experience the ‘cartesian explosion’ problem. This relates to how we can get lots of duplicated data for each join we do. Mostly this duplicated data is handled fine but if there is enough of it, it can affect performance.
One possible resolution for the ‘cartesian explosion’ problem is to split the queries up when serving them against the DB and join the result sets back on the client side. As of version 5.0 query splitting is possible in Entity Framework Core. The syntax is simple…
In the 1st example below (click the image for a larger view in a new window) we can see the EF Core default which is to issue a single query which left joins blogs and posts. We can see some duplicated data highlighted in red. In this case we only have a small amount of duplication as we are only joining one table and it is quite narrow without many columns.
In the 2nd example below we include the new .AsSplitQuery() syntax and can see that this produces two queries and two result sets which EF Core will combine. Two potential issues with using AsSplitQuery() include…
Data can change in between the first and second queries. Consider using transactions to mitigate this.
More roundtrips due to multiple queries. If latency is high this can affect performance. Consider using MARS to potentially help here if using SQL Server.
Entity Framework Core 5.0 now supports the translation of String.FirstOrDefault() LINQ queries.
In EF Core 3.1 the following would fail…
with an error message similar to below but in 5.0 it translates into a query using substring().
Note… a potential performance gotcha with EF Core < 3.0 was that any queries it couldn’t translate were evaluated on the client (.NET side). This often resulted in performance problems in production as huge numbers of records could be returned to the client AND THEN filtered. Since version 3.0 Entity Framework Core will throw an exception if anything can’t be translated but watch out for this in earlier versions.
If you’re using Entity Framework Core with the database first approach and re-scaffold you’ll see that by default EF Core will create an OnConfiguring overload with a connection string so that the context is immediately usable.
In EF Core 5.0 if you already have your connection string defined in Startup.cs -> ConfigureServices like the first image below or through some other approach you can now suppress the output of OnConfiguring in the generated DbContext class.
The relevant flag is..
-NoOnConfiguring for the package manager console –no-onConfiguring for the CLI approach
AsNoTracking() has been around in Entity Framework for a while. Its ideal to use when pulling back a collection of items which won’t be updated (a listing page for example) as it gives a little performance boost in these cases.
The default behaviour for AsNoTracking() is not to perform identity resolution. This means if your query returns 4 books and their authors, you’ll get 8 instances in total even if 2 books have the same author.
To enable identity resolution with no tracking queries EF Core uses a mini or stand-alone change tracker in the background which goes out of scope and is garbage collected as soon as the query results have been materialized.
Note… AsNoTrackingWithIdentityResolution() is a little slower than AsNoTracking() but still quicker than regular queries which utilize full change tracking.