'A second operation started on this context, Domain Event EF Core 3.1

I'm using Domain Event to update some tables. I have created a class that inherits INotificationHandlers like this:

  public class DamageTypeEvents:INotificationHandler<DamageTypeWasAddedEvent>,
                                INotificationHandler<AttributeWasUnlinkedEvent>,
                                INotificationHandler<AttributeWasLinkedEvent>
  {
    private readonly MyContext _writeContext;

    public DamageTypeEvents( MyContext writeContext )
    {
      _writeContext = writeContext;
    }

in app service I send a list of attributes and will link and unlink these attributes to DamageTypes.

public async Task Handle( AttributeWasUnlinkedEvent notification, CancellationToken cancellationToken )
=>
//codes removed for brevity
await _writeContext.SaveChangesAsync( cancellationToken )

public async Task Handle( AttributeWasLinkedEvent notification, CancellationToken cancellationToken )
=>
//codes removed for brevity
await _writeContext.SaveChangesAsync( cancellationToken )

when AttributeWasLinkedEvent fires, then it throws following error:

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

I think it can be fixed by using a DbContextFactory but EF Core 3.1 does not provide this feature.

By the way if I change the DbContext lifetime to transient it will be fixed, but I am wondering if there is any other solution?

Update:

here is how I use link and unlink in my entities.

//in command handler:
  .Check( x=>x.DamageType.UnlinkAttributes( x.Attributes ) )
  .Check( x=>x.DamageType.LinkAttributes(x.Attributes) )
  

//and in my entities

public Result LinkAttributes( List<Attribute> attributes )
    {
      var addedAttributes = attributes.Except( _attributes );
      _attributes.AddRange( addedAttributes );
      AddEvent( new AttributeWasLinkedEvent( Id));
      return Result.Success();
    }

    public Result UnlinkAttributes( List<Attribute> attributes )
    {
      var unlinkedAttributes = _attributes.Except( attributes );
      foreach ( var attribute in unlinkedAttributes ) {
         attribute.Delete();
         AddEvent( new AttributeWasUnlinkedEvent( Id,attribute.Id ));
      }
      return Result.Success();
    }


Solution 1:[1]

This can be fixed by enabling Multiple Active Result Sets in your connection string:

string connectionString = "Data Source=MSSQL1;" +
"Initial Catalog=AdventureWorks;Integrated Security=SSPI;" +  
"MultipleActiveResultSets=True";  

For reference: https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/enabling-multiple-active-result-sets

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Joest