EF performance tips
Tags: ef, dotnet, performance, programming
Published: 2023-07-26 13:35:55

If you are working with Entity Framework, you might be interested in these two tips to improve your performance and avoid common pitfalls.


#### Do not use the `DetectChanges` method unnecessarily, as it can consume a lot of CPU time and memory.

The `DetectChanges` method is used by Entity Framework to synchronize the state of the entities in the context with the changes made in the database. It is called automatically by many methods, such as `SaveChanges`, `Find`, and `Include`. However, sometimes you might be tempted to call it _manually_, for example, to force validation or to refresh the state of an entity. This can be a costly operation, especially if you have a large number of entities in the context. Therefore, you should avoid calling `DetectChanges` unless you really need to.

One way to reduce the number of calls to `DetectChanges` is to use the `ChangeTracker.AutoDetectChangesEnabled` property. You can set it to `false`, and then call `DetectChanges` explicitly only when you need to. For example:

```csharp
using (var context = new BlogContext())
{
// Disable automatic change detection
context.ChangeTracker.AutoDetectChangesEnabled = false;

// Add some entities
context.Blogs.Add(new Blog { Name = "EF Tips" });
context.Blogs.Add(new Blog { Name = "C# Corner" });

// Call DetectChanges before saving
context.ChangeTracker.DetectChanges();
context.SaveChanges();
}
```

However, be careful not to disable change detection for too long, as it can lead to inconsistent or stale data in the context. You should always re-enable it or call `DetectChanges` before querying or saving data.


#### Do not disable tracking for entities that you need to update or delete later, as it can cause concurrency issues and data loss.

Another way to improve performance with Entity Framework is to use the `AsNoTracking` method. This method returns a query that does not track the entities in the context, meaning that they are not cached or monitored for changes. This can reduce memory usage and overhead, especially for read-only scenarios.

However, you should not use `AsNoTracking` for entities that you need to update or delete later, as it can cause problems. For example:

```csharp
using (var context = new BlogContext())
{
// Query for a blog without tracking
var blog = context.Blogs.AsNoTracking()
.FirstOrDefault(b => b.Name == "EF Tips");

// Modify the blog name
blog.Name = "EF Tricks";

// Try to update the blog
context.Update(blog); // This will fail!
context.SaveChanges();
}
```

In this example, the Update method will fail because the blog entity is not tracked by the context. Therefore, Entity Framework does not know how to generate the SQL update statement for it.

Moreover, even if you attach the entity to the context before updating it, you might still encounter concurrency issues or data loss, because Entity Framework does not have the original values of the entity to perform optimistic concurrency checks or detect conflicts.

Therefore, you should only use `AsNoTracking` for entities that you do not need to modify later. If you need to update or delete an entity, you should either query it with tracking enabled, or use an alternative method such as `Find` or `FromSqlRaw`.