---
title: "Disabling thread safety check in Entity Framework"
description: "In this blog post we will have a look into how to disable the thread safety check in Entity Framework. What are the implications of doing so and how to do it."
updated: 2025-08-04
tags: ["C#", "EF", "Performance"]
canonical: "https://steven-giesel.com/blogPost/f1c14e0f-840c-4dd6-921c-364298a35d6f/disabling-thread-safety-check-in-entity-framework"
---

# Disabling thread safety check in Entity Framework

In this blog post we will have a look into how to disable the thread safety check in Entity Framework. What are the implications of doing so and how to do it.

## Thread safety check in Entity Framework
`DbContext` by default is not thread safe. Therefore the `DbContext` tries to detect whether or not it is being used in a thread safe manner. Imagine the following code:

```csharp
using var context = new MyDbContext();

var task1 = context.Users.ToListAsync();
var task2 = context.BlogPosts.ToListAsync();

await Task.WhenAll(task1, task2);
```

This will throw an exception because the `DbContext` is being used in two different threads at the same time. If you want to do the above, you have to resort to the `IDbContextFactory` to create a new `DbContext` for each task:

```csharp
public MyService(IDbContextFactory<MyDbContext> dbContextFactory)
{
    _dbContextFactory = dbContextFactory;
}

var dbContext1 = _dbContextFactory.CreateDbContext();
var dbContext2 = _dbContextFactory.CreateDbContext();
var task1 = dbContext1.Users.ToListAsync();
var task2 = dbContext2.BlogPosts.ToListAsync();
await Task.WhenAll(task1, task2);
```

## Disabling the thread safety check
That check comes with a performance "penalty" (that is very minor). If you want to disable the thread safety check, you can do so by setting the `DbContextOptionsBuilder.EnableThreadSafetyChecks` property to `false`:

```csharp
var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>()
    .UseSqlite("Data Source=mydatabase.db")
    .EnableThreadSafetyChecks(false);
```

**Word of caution here:** Doing this will disable the thread safety check and you have to be 100% sure that you are not using the `DbContext` in a different thread at the same time.
For example by using the `IDbContextFactory` to create a new `DbContext` for each task as shown above that makes the `DbContext` thread safe. 

If you fail to ensure that, you will run into hard-to-debug issues that can lead to data corruption or other unexpected behavior in your application. (I will put this into the resources section down below).

The small upside is: Performance gain. Let's have a check here (code is also at the end of the post):

```csharp
[MemoryDiagnoser]
public class EntityFrameworkBenchmark
{
    private const int Iterations = 1000;
    private TestDbContextWithThreadSafety? _dbContextWithThreadSafety;
    private TestDbContextWithoutThreadSafety? _dbContextWithoutThreadSafety;

    [GlobalSetup]
    public void Setup()
    {
        _dbContextWithThreadSafety = new TestDbContextWithThreadSafety();
        _dbContextWithThreadSafety.Database.EnsureCreated();
        
        _dbContextWithoutThreadSafety = new TestDbContextWithoutThreadSafety();
        _dbContextWithoutThreadSafety.Database.EnsureCreated();
    }

    [GlobalCleanup]
    public async Task Cleanup()
    {
        if (_dbContextWithThreadSafety is not null)
        {
            await _dbContextWithThreadSafety.DisposeAsync();
        }
        
        if (_dbContextWithoutThreadSafety is not null)
        {
            await _dbContextWithoutThreadSafety.DisposeAsync();
        }
    }

    [Benchmark(Baseline = true)]
    public async Task<List<TestEntity>> WithThreadSafetyChecks()
    {
        var results = new List<TestEntity>();
        for (var i = 0; i < Iterations; i++)
        {
            results.AddRange(await _dbContextWithThreadSafety!.TestEntities.ToListAsync());
        }

        return results;
    }

    [Benchmark]
    public async Task<List<TestEntity>> WithoutThreadSafetyChecks()
    {
        var results = new List<TestEntity>();
        for (var i = 0; i < Iterations; i++)
        {
            results.AddRange(await _dbContextWithoutThreadSafety!.TestEntities.ToListAsync());
        }

        return results;
    }
}
```

And here are the results:
```no-class
| Method                    | Mean      | Error     | StdDev    | Ratio | RatioSD | Gen0     | Gen1     | Allocated | Alloc Ratio |
|-------------------------- |----------:|----------:|----------:|------:|--------:|---------:|---------:|----------:|------------:|
| WithThreadSafetyChecks    | 10.090 ms | 0.1381 ms | 0.1224 ms |  1.00 |    0.02 | 875.0000 | 437.5000 |   6.98 MB |        1.00 |
| WithoutThreadSafetyChecks |  9.423 ms | 0.1332 ms | 0.1112 ms |  0.93 |    0.02 | 843.7500 | 421.8750 |    6.8 MB |        0.97 |
```

A very small gain - keep in mind that there is exactly 0 data coming back from the database, so this is just a pure performance test of the `DbContext` itself.
If we would have data coming back from the database, the performance gain would be even smaller (relative to the overall runtime)!

So does it make sense to use that? Well, as a very advanced use case, maybe. But using something like a pooled `IDbContextFactory` is a much better option in my opinion before resorting to this.

## Resources
* Official Microsoft Documentation for Entity Framework: https://learn.microsoft.com/en-us/ef/core/performance/advanced-performance-topics?tabs=with-di%2Cexpression-api-with-constant
* Source code for this blog post: https://github.com/linkdotnet/BlogExamples/tree/main/EFDisableThreadSafety
* Source code for many of my blog posts: https://github.com/linkdotnet/BlogExamples