<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Temitope Okelola</title>
    <description>The latest articles on DEV Community by Temitope Okelola (@temitope_okelola).</description>
    <link>https://dev.to/temitope_okelola</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3877086%2F18569b0f-87c1-42e5-9cc6-c0456997d569.png</url>
      <title>DEV Community: Temitope Okelola</title>
      <link>https://dev.to/temitope_okelola</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/temitope_okelola"/>
    <language>en</language>
    <item>
      <title>Everyone Using DbContext Concurrently Is Making This Mistake</title>
      <dc:creator>Temitope Okelola</dc:creator>
      <pubDate>Tue, 14 Apr 2026 08:29:40 +0000</pubDate>
      <link>https://dev.to/temitope_okelola/everyone-using-dbcontext-concurrently-is-making-this-mistake-24bg</link>
      <guid>https://dev.to/temitope_okelola/everyone-using-dbcontext-concurrently-is-making-this-mistake-24bg</guid>
      <description>&lt;p&gt;I Googled it. I asked AI. I tried every Stack Overflow answer I could find. Nothing worked. Then I found the fix completely by accident — in a book I wasn't even reading for that reason.&lt;/p&gt;

&lt;p&gt;Here's what was actually going on — explained simply enough that even if you're new to .NET, you'll get it immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Was Trying to Do
&lt;/h2&gt;

&lt;p&gt;I was working on a feature that needed to call two different API operations at the same time — concurrently. Run both, wait for both to finish, move on. Simple enough in theory.&lt;/p&gt;

&lt;p&gt;Except the moment I did, my app threw this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;InvalidOperationException: A second operation was started on this context
instance before a previous operation completed. This is usually caused
by different threads using the same instance of DbContext.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I stared at it. Searched for it. Tried things for hours. Nothing matched my exact situation. I almost scrapped the whole concurrent approach and just ran them one after the other.&lt;/p&gt;

&lt;p&gt;Then completely by accident — reading something for an entirely different reason — I landed on exactly what was wrong. One page. That's all it took.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, What Even Is DbContext?
&lt;/h2&gt;

&lt;p&gt;If you're using EF Core to talk to your database in .NET, &lt;code&gt;DbContext&lt;/code&gt; is the main object you work with. You use it to query data, save records, update things — everything database-related goes through it.&lt;/p&gt;

&lt;p&gt;When you write something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;_context&lt;/code&gt; is your &lt;code&gt;DbContext&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Think of it like a &lt;strong&gt;shopping basket&lt;/strong&gt;. You use it to collect items, track what's changed, then check out (save to the database). It's designed to be used by &lt;strong&gt;one person at a time&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: I Was Sharing One Basket Between Two People at the Same Time
&lt;/h2&gt;

&lt;p&gt;When I ran two API operations concurrently, both of them were trying to use the &lt;strong&gt;same &lt;code&gt;DbContext&lt;/code&gt; instance&lt;/strong&gt; simultaneously.&lt;/p&gt;

&lt;p&gt;EF Core does not allow this. At all.&lt;/p&gt;

&lt;p&gt;It's not a bug — it's by design. &lt;code&gt;DbContext&lt;/code&gt; is built to handle &lt;strong&gt;one operation at a time&lt;/strong&gt;. The moment two things try to use it at the same time, it throws that error.&lt;/p&gt;

&lt;p&gt;Here's exactly what I was doing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Looks fine. Completely breaks at runtime.&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;task1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;task2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsActive&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WhenAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both tasks start at the same time. Both reach for &lt;code&gt;_context&lt;/code&gt;. EF Core sees two operations hitting the same instance simultaneously and throws the exception.&lt;/p&gt;

&lt;p&gt;Perfectly reasonable looking code. Completely broken behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does This Happen? (The Simple Explanation)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;DbContext&lt;/code&gt; keeps track of a lot of things internally — what data it has loaded, what has changed, what needs to be saved. It maintains all of this as &lt;strong&gt;state in memory&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If two operations are modifying that state at the same time, things get corrupted. It's the same reason you wouldn't let two people edit the same Word document simultaneously without something like Google Docs coordinating it.&lt;/p&gt;

&lt;p&gt;EF Core doesn't coordinate it. It just says: &lt;strong&gt;one at a time, please&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix: Give Each Operation Its Own DbContext
&lt;/h2&gt;

&lt;p&gt;Once you understand the problem, the solution makes complete sense.&lt;/p&gt;

&lt;p&gt;Instead of sharing one &lt;code&gt;DbContext&lt;/code&gt; between both operations, give &lt;strong&gt;each operation its own separate instance&lt;/strong&gt;. Completely independent — they don't know about each other, they can't conflict.&lt;/p&gt;

&lt;p&gt;To do this in .NET, you use something called &lt;code&gt;IServiceScopeFactory&lt;/code&gt;. Don't let the name scare you — all it does is let you create a &lt;strong&gt;new isolated environment&lt;/strong&gt; (called a scope) that comes with its own fresh &lt;code&gt;DbContext&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's the fixed version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Each operation gets its own DbContext — no conflicts&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetOrdersAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_scopeFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateScope&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServiceProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetProductsAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_scopeFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateScope&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServiceProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsActive&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Now run them concurrently — completely safe&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;task1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetOrdersAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;task2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetProductsAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WhenAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inject &lt;code&gt;_scopeFactory&lt;/code&gt; into your class like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IServiceScopeFactory&lt;/span&gt; &lt;span class="n"&gt;_scopeFactory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceScopeFactory&lt;/span&gt; &lt;span class="n"&gt;scopeFactory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_scopeFactory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scopeFactory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No special packages. No extra configuration. Fully built into .NET.&lt;/p&gt;




&lt;h2&gt;
  
  
  Breaking It Down Line by Line
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_scopeFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateScope&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creates a brand new isolated environment. Think of it as opening a fresh browser tab — nothing from the other tab carries over.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServiceProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gets a fresh &lt;code&gt;DbContext&lt;/code&gt; that belongs exclusively to this scope. It has zero knowledge of what the other operation is doing.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;using&lt;/code&gt; keyword at the start means when the method finishes, the scope automatically cleans itself up. The &lt;code&gt;DbContext&lt;/code&gt; it created gets properly disposed. You don't have to do anything extra.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Stack Overflow and AI Couldn't Help Me
&lt;/h2&gt;

&lt;p&gt;Most answers online assume you're hitting this error inside a background service — a very common place this same problem appears. My situation was different: two concurrent API calls inside regular application logic. Same error, different context, different search terms. That's why nothing was showing up.&lt;/p&gt;

&lt;p&gt;If you're not searching with exactly the right words, you'll scroll right past the answer without recognising it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The One Thing to Remember
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;DbContext&lt;/code&gt; is not built for sharing. The moment two operations run concurrently and reach for the same instance, you'll hit this error.&lt;/p&gt;

&lt;p&gt;The rule is simple: &lt;strong&gt;one concurrent operation, one DbContext&lt;/strong&gt;. Use &lt;code&gt;IServiceScopeFactory&lt;/code&gt; to create a fresh one for each and you'll never see that exception again.&lt;/p&gt;

&lt;p&gt;Sometimes the answer isn't on the first page of Google. Keep digging — it's always somewhere.&lt;/p&gt;

&lt;p&gt;Has this ever happened to you — spending hours searching only to find the answer somewhere completely unexpected? Drop it in the comments.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>webdev</category>
      <category>efcore</category>
    </item>
  </channel>
</rss>
