A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext

Pedro Otávio 20 Reputation points
2024-06-17T17:33:53.32+00:00

I have a project using Azure Function with ASP.NET Core 8 and Service Bus, for data access I use EF Core.

I'm getting hit a lot and we still haven't found the cause of the error:

"A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext"

This Azure Function project has 10 queues implemented as shown in the example below:

[Function("object_insert")]
public async Task CreateObject(
[ServiceBusTrigger("object.insert", Connection = "AzureBusConnection", AutoCompleteMessages = false)]
    ServiceBusReceivedMessage message,
    ServiceBusMessageActions messageActions,
    FunctionContext functionContext)
{
    string payload = Encoding.UTF8.GetString(message.Body);

    try
    {
        if (string.IsNullOrEmpty(payload)) throw new ArgumentException("Body null!");

        var obj = JsonConvert.DeserializeObject<RastreabilidadeResponseDTO>(payload, new JsonSerializerSettings
        {
            TypeNameHandling = TypeNameHandling.Auto,
            NullValueHandling = NullValueHandling.Ignore,
        });

        if (obj != null)
        {
            await mediator.Publish(new TraceEtiquetaEvent(obj.EtiquetaId, obj.TraceType, obj.EtiquetaAnaliseId, obj.Description));
        }

        await messageActions.CompleteMessageAsync(message);
    }
    catch (Exception er)
    {            
        await messageActions.DeadLetterMessageAsync(message, null, er.Message, er.StackTrace);
    }
}

To open the connection, I do the following:

_services.AddDbContext<SQLServerDbContext>(options => options.UseSqlServer(connection, x =>
{
    x.CommandTimeout(180);
}), ServiceLifetime.Transient);

_services.AddTransient<IBaseRepository, BaseRepository>();
_services.AddTransient<IUserRepository, UserRepository>();

Any ideas on how to resolve this?

Entity Framework Core
Entity Framework Core
A lightweight, extensible, open-source, and cross-platform version of the Entity Framework data access technology.
750 questions
Azure Service Bus
Azure Service Bus
An Azure service that provides cloud messaging as a service and hybrid integration.
635 questions
Azure Functions
Azure Functions
An Azure service that provides an event-driven serverless compute platform.
5,086 questions
{count} votes

Accepted answer
  1. Michael Taylor 54,806 Reputation points
    2024-06-17T18:18:42.7633333+00:00

    This error is caused by you using the same DbContext instance on multiple threads at the same time. This is generally a scoping issue. I don't see in the code you posted where it is making any use of the DB context so it is hard to say where the problem is at this point. Confirm that every use of the context is from the same DI type you configured. Also I notice that you're using transient scope here which is probably not correct. Transient means every request gets a new copy. Thus if your repos each request the DbContext they will end up getting different copies of the type which means they cannot interact with potentially shared data. In general you should prefer AddScoped unless you need a new instance each time the call is made.

    It can also happen if you are using a single DbContext instance but in the middle of it being used (such as a deferred LINQ call), you then start another query that requires it to connect to the DB again. Since the first query is still in progress it cannot allow another connection. This is harder to recognize in code because we have no way of knowing how the queries might interact at runtime. One scenario I've seen it happen is when enumerating a resultset and lazy loading is triggered after the query has been run on the database but while it is still enumerating the results. The connection cannot be reused because it is still reading the data.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.