I have a very long running operation that could be split into many shorter ones - if I was able to call DbContext
asynchronously.
First of all, a data service:
public class MyDataService : IMyDataService
{
private readonly IMyRepository _arepository;
private readonly ITransactionScope _txScope;
public MyDataService(IMyRepository repository, ITransactionScope txScope)
{
_repository = repository;
_txScope = txScope;
}
public async Task<Result> CreateOrAppendAsync(SomeObject[] someObjects)
{
return await _txScope.DoInTransactionAsync(
_principal.GetName(),
"create-or-append",
null,
async () => await _repository.CreateOrAppendAsync(someObjects));
}
}
And then the repository:
public class MyRepository : IRepository
{
private readonly InternalDbContext _dbContext;
public Repository(InternalDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<Result> CreateOrAppendAsync(SomeObject[] someObjects)
{
var tasks = new List<Task<PartOfResult>>();
foreach (var batch in someObjects.Split(10))
{
tasks.Add(Task.Run(() =>
{
// do something with _dbContext to get result
}));
}
var results = await Task.WhenAll(tasks.ToArray());
return results.Combine();
}
}
This of course does not work because of:
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. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.
The question is: How would I do this correctly? Previously I've just copied the DbContext
, but since all of this is part of the same transaction, that is not possible. The Postgres database should be able to handle multiple calls, Dotnet has such nice keywords to make parallel processing easy, but how does EF Core work together with all of this.