Entity Framework mergeoption notracking bad performance

Entity FrameworkEntity Framework-4Linq to-Entities

Entity Framework Problem Overview


I have a strange behavior trying to execute a query declaring ObjectQuery MergeOption to "NoTracking", in this case entity framework should not attach any entity and not create the relative ObjectStateEntry to track entity state.

The problem is that instead of increase performance it get worse, the same query takes like 10 seconds with default mergeoption (that is AppendingOnly) and more the 1 minutes if I try to specify notracking

Does someone have an explanation for this??

Entity Framework Solutions


Solution 1 - Entity Framework

If you disable change tracking by setting the NoTracking merge option you save the performance costs of attaching objects to the contexts but on the other hand you also lose identity management.

This means that potentially much more objects - many with the same key - will be materialized.

Example: Suppose you have a User entity with a Roles collection as navigation property. Also suppose you have 1 million users in the database and all users are in the same 10 roles, i.e. every user has a roles collection with 10 elements. If you run the following query...

var users = context.Users.Include("Roles").ToList();

...the number of materialized and instantiated objects depends on the merge option:

  • If you don't use NoTracking you will have 1.000.010 objects in memory, namely 1 million users, but only 10 roles because identity mapping will ensure that only 1 role per key is materialized and attached to the context. The same 10 role instances are used for all user's Roles collection.

  • If you use NoTracking however, EF won't attach objects to the context, hence identity management is disabled and you will have 11.000.000 objects in memory: 1 million users and 10 role instances per user, i.e. 10 million role objects. So, you have more than 10 times as many materialized objects as when the objects are attached to the context.

Object materialization is classified with "moderate" performance costs:

> Operation: Materializing the objects >
> Relative Cost: Moderate >
> Frequency: Once for each object that a query returns. >
>
> Comments: > The process of reading the returned DbDataReader object and creating > objects and setting property values that are based on the values in > each instance of the DbDataRecord class. If the object already exists > in the ObjectContext and the query uses the AppendOnly or > PreserveChanges merge options, this stage does not affect performance.

In other words: If the query uses the NoTracking merge option, this stage does affect performance and it might be possible that the performance benefits of disabled change tracking are destroyed by the drawbacks of disabled identity management and multiplied object materialization.

Since EF Core 5.0 there is the additional option 'NoTrackingWithIdentityResolution' which disables general tracking but will do identity resolution.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMaRufView Question on Stackoverflow
Solution 1 - Entity FrameworkSlaumaView Answer on Stackoverflow