Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
ManikandanUlagu opened this issue Mar 18, 2022 · 5 comments

Comments

@ManikandanUlagu
Copy link

ManikandanUlagu commented Mar 18, 2022

Hello team,
I am working on .Net 5 project with EF core and using PostgreSQL as Database and getting below error when I send two request at the same time... Any ideas of what could be causing this issue?

Error: A second operation was started on this context before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext,

I have injected my db context as below :
services.AddDbContext(options =>
options.UseNpgsql(config["ConnectionStrings:DefaultConnection"]), ServiceLifetime.Transient);

and Sample DbContext model:

   public virtual DbSet<RunTestData> RunTestData { get; set; }

OnModelCreating(...)
{

modelBuilder.Entity<RunTestData>(entity =>
            {
                entity.HasKey(e => e.RuntestId)
                    .HasName("run_test_data_pkey");

                entity.ToTable("run_test_data");

                entity.Property(e => e.RuntestId)
                    .HasColumnName("runtest_id")
                    .UseIdentityAlwaysColumn();

                entity.Property(e => e.CreatedBy)
                    .HasMaxLength(100)
                    .HasColumnName("created_by");

                entity.Property(e => e.CreatedDatetime).HasColumnName("created_datetime");

                entity.Property(e => e.Data)
                    .HasColumnType("character varying")
                    .HasColumnName("data");

                entity.Property(e => e.Uuid)
                    .IsRequired()
                    .HasColumnType("character varying")
                    .HasColumnName("uuid");
            });
}

And the below method is for inserting the data

 public async Task<int> AddTestResponse(TestResponseDto testResponse)
        {
            try
            {
                var testResponseDetails = _entityMapper.Map<TestResponseDto, RunTestData>(testResponse);
                _entities.Set<RunTestData>().Add(testResponseDetails);
                await _entities.SaveChangesAsync();
                return testResponseDetails.RuntestId;
            }
            catch (Exception)
            {
                throw;
            }

        }

Error Summary:

2022-03-18-14:59:19 - info: [stdf_service] - fail: Microsoft.EntityFrameworkCore.Update[10000]
      An exception occurred in the database while saving changes for context type 'MKS.StdfIntegration.DataModel.WandDbContext.WandContext'.
      System.InvalidOperationException: A second operation was started on this context before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.
         at Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection()
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(DbContext _, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
         at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
      System.InvalidOperationException: A second operation was started on this context before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.
         at Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection()
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(DbContext _, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
         at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)

2022-03-18-14:59:19 - info: [stdf_service] -    at Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection()
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(DbContext _, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
   at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
   at MKS.StdfIntegration.DataAccess.TestResultDataRepository.AddTestResponse(TestResponseDto testResponse) in C:\KS\WireBond-Dev-Refactor\wirebond\services\stdf\StdfIntegration\StdfIntegration.DataAccess\TestResultDataRepository.cs:line 68
   at MKS.StdfIntegration.Business.Managers.TestResultDataManager.AddTestResponse(TestResponseDto testResponse) in C:\KS\WireBond-Dev-Refactor\wirebond\services\stdf\StdfIntegration\StdfIntegration.Business\Managers\TestResultDataManager.cs:line 52
   at MKS.StdfIntegration.RouteManager.RunTestResponseData(String message) in C:\KS\WireBond-Dev-Refactor\wirebond\services\stdf\StdfIntegration\StdfIntegration\RouteManager.cs:line 458

2022-03-18-14:59:23 - info: [stdf_service] - fail: Microsoft.EntityFrameworkCore.Update[10000]
      An exception occurred in the database while saving changes for context type 'MKS.StdfIntegration.DataModel.WandDbContext.WandContext'.
      System.InvalidOperationException: The property 'RunTestHeader.HeaderId' has a temporary value while attempting to change the entity's state to 'Unchanged'. Either set a permanent value explicitly, or ensure that the database is configured to generate values for this property.
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.AcceptChanges()
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.AcceptAllChanges(IReadOnlyList`1 changedEntries)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(DbContext _, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
         at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
      System.InvalidOperationException: The property 'RunTestHeader.HeaderId' has a temporary value while attempting to change the entity's state to 'Unchanged'. Either set a permanent value explicitly, or ensure that the database is configured to generate values for this property.
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.AcceptChanges()
         at Micros
2022-03-18-14:59:23 - info: [stdf_service] - oft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.AcceptAllChanges(IReadOnlyList`1 changedEntries)
         at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(DbContext _, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
         at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)

@roji pls help on this. Thanks

@roji
Copy link
Member

roji commented Mar 18, 2022

@ManikandanUlagu Map() is not part of EF Core - you're using some additional 3rd-party library, so it's difficult to know what's going on.

Please submit a full, runnable code sample; I can't really help with partial code snippets and unknown 3rd-party libraries.

@ManikandanUlagu
Copy link
Author

@ManikandanUlagu Map() is not part of EF Core - you're using some additional 3rd-party library, so it's difficult to know what's going on.

Please submit a full, runnable code sample; I can't really help with partial code snippets and unknown 3rd-party libraries.

@roji I have used AutoMapper for map DTO model to db model. it's not issue. But I have changed, Please find the below sample runnable code. also let me know if you need any other details from my end. Thanks

Please find the below sample code.

DB Injection:
services.AddDbContext(options =>
options.UseNpgsql(config["ConnectionStrings:DefaultConnection"]), ServiceLifetime.Transient);

DB Model:
public partial class RunTestData
{
public RunTestData()
{
RunTestHeader = new HashSet();
}

    public int RuntestId { get; set; }
    public string Uuid { get; set; }
    public string Data { get; set; }
    public DateTime? CreatedDatetime { get; set; }
    public string CreatedBy { get; set; }

    public virtual ICollection<RunTestHeader> RunTestHeader { get; set; }
}

OnModelCreating:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity(entity =>
{
entity.HasKey(e => e.RuntestId)
.HasName("run_test_data_pkey");

            entity.ToTable("run_test_data");

            entity.Property(e => e.RuntestId)
                .HasColumnName("runtest_id")
                .UseIdentityAlwaysColumn();

            entity.Property(e => e.CreatedBy)
                .HasMaxLength(100)
                .HasColumnName("created_by");

            entity.Property(e => e.CreatedDatetime).HasColumnName("created_datetime");

            entity.Property(e => e.Data)
                .HasColumnType("character varying")
                .HasColumnName("data");

            entity.Property(e => e.Uuid)
                .IsRequired()
                .HasColumnType("character varying")
                .HasColumnName("uuid");
        });
}

Insert Method:
public async Task AddTestResponse(RunTestData runData)
{
try
{

            _entities.Set<RunTestData>().Add(runData);
            await _entities.SaveChangesAsync();
            return testResponseDetails.RuntestId;
        }
        catch (Exception)
        {
            throw;
        }

}

Thanks

@roji
Copy link
Member

roji commented Mar 20, 2022

@ManikandanUlagu the above is still a bunch of snippets - I cannot run it to see the error. To actually investigate I'd need a runnable project I can start.

At the end of the day, you're somehow using the same DbContext instance from two threads. That probably means you're keeping a reference to a context somewhere and improperly using it, or something similar.

PS please take a look at how your code samples look - it's hard to understand them. When posting code on github, use fenced code blocks (with ```) to make them readable and use syntax highlighting (see your original post above which I've edited). Good indentation also helps the reader understand what's going on.

@ManikandanUlagu
Copy link
Author

@ManikandanUlagu the above is still a bunch of snippets - I cannot run it to see the error. To actually investigate I'd need a runnable project I can start.

At the end of the day, you're somehow using the same DbContext instance from two threads. That probably means you're keeping a reference to a context somewhere and improperly using it, or something similar.

PS please take a look at how your code samples look - it's hard to understand them. When posting code on github, use fenced code blocks (with ```) to make them readable and use syntax highlighting (see your original post above which I've edited). Good indentation also helps the reader understand what's going on.

@roji Thank you for your response. For resolve my issue, I have changed my db context DI from AddDbContext to AddDbContextFactory and now its working as expected.
I have referred below links.
https://docs.microsoft.com/en-us/ef/core/dbcontext-configuration/
dotnet/efcore#25273
ErikEJ/EFCorePowerTools#991
dotnet/efcore#24124

Thanks
Manikandan Ulagu

@roji
Copy link
Member

roji commented Mar 20, 2022

Happy that you managed to find the fix.

@roji roji closed this as completed Mar 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants