Является ли собственная область действия плохим решением для одновременного доступа к DbContext? - PullRequest
0 голосов
/ 05 февраля 2020

Я столкнулся с этой ошибкой в ​​одноэлементной службе, когда два экземпляра одного и того же класса пытались использовать один и тот же метод, который использует репозиторий

Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
   at Npgsql.EntityFrameworkCore.PostgreSQL.Update.Internal.NpgsqlModificationCommandBatch.ConsumeAsync(RelationalDataReader reader, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(DbContext _, ValueTuple`2 parameters, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IReadOnlyList`1 entriesToSave, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)

Чтобы устранить эту проблему, я нашел решение с использованием собственной области действия в Autofa c

private readonly Func<Owned<IProductRepository>> productRepositoryFactory;
...
using (var repositoryOwned = productRepositoryFactory())
{
   await repositoryOwned.Value.DeleteRangeAsync(idsToRemove);
}

Это решило проблему, но я боюсь, что производительность будет затронута из-за спама создания и удаления DbContext (используемый DbContext зарегистрирован согласно зависимости). Есть ли лучшее решение этой проблемы, которое не повлияет на производительность таким образом?

1 Ответ

0 голосов
/ 05 февраля 2020

Создание области является единственным способом, если вы планируете передать контекст в метод asyn c. Например, вы можете использовать DI для IServiceProvider serviceProvider в конструкторе, а затем использовать его следующим образом:

 using (var scope = _serviceProvider.CreateScope())
 {
     var service = scope.ServiceProvider.GetRequiredService<IYOURSERVICE>();
     ...
 }
...