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??
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.