Поскольку он имеет область действия, я получаю исключение. Вторая операция началась в этом контексте до завершения предыдущей операции. Поскольку службы используют репозитории, которые используют один и тот же контекст базы данных для одного запроса API.
Проблема кажется универсальной: как использовать блоки потока данных (множественные потоки TPL) с EntityFramework и его DbContext. p>
Найденные мной решения:
- Установите для DbContext значение Transient во внедрении зависимостей ASP .NET.
- Создание экземпляра DbContext для каждого потока.
ПЛЮС: Я читаю в Интернете, что это предпочтительный способ.
Минусы :
Во время загрузки я использую множество сервисов. Я вызываю частный метод, который вызывает другой метод, который вызывает разные классы сервисов и т. д.
Мне удалось заставить его работать, создав статический класс AmbientScope и предоставив сервисы на уровне потока в каждом методе.
var serviceA = AmbientServiceScope.Current?.GetRequiredService();
var serviceB = AmbientServiceScope.Current?.GetRequiredService();
var serviceC = AmbientServiceScope.Current?.GetRequiredService();
var mediator = AmbientServiceScope.Current?.GetRequiredService();
if (serviceA is null || serviceB is null || ...)
{
throw new InvalidOperationException("No ambient scope available!");
}
// continue method logic
// public method because its used by other services/requests to check a file is complete,
// not only by UploadWithDataflow
}
Проблемы:
[*]Много шаблонного кода.
[*] Если метод используется из нескольких запросов API (Загрузка файлов, Проверка завершения файла), то запросы, которые не используют потоки, все равно должны создать Ambient Scope для работы.
Мне снова нужен шаблонный код и внедрить IServiceScopeFactory повсюду:
using var scope = serviceScopeFactory.CreateScope();
using (AmbientServiceScope.SetScope(scope.ServiceProvider))
{
...
}
Это распространенная проблема. Должно быть простое решение.
AmbientScope
public static class AmbientServiceScope
{
private static readonly AsyncLocal _currentScope = new();
public static IServiceProvider? Current => _currentScope.Value;
public static IDisposable SetScope(IServiceProvider serviceProvider)
{
var previous = _currentScope.Value;
_currentScope.Value = serviceProvider;
return new DisposeAction(() => _currentScope.Value = previous);
}
private class DisposeAction(Action disposeAction) : IDisposable
{
public void Dispose() => disposeAction();
}
}
Подробнее здесь: https://stackoverflow.com/questions/792 ... db-context
Мобильная версия