Как исправить несколько контекстов базы данных в области ASP - PullRequest
0 голосов
/ 29 мая 2019

У меня есть размещенный сервис, который использует контекст БД, и сервис с областью действия, который также использует контекст БД. Это выглядит примерно так

public class HostedWorker : BackgroundService
{
    private readonly IServiceScopeFactory scopeFactory;

    public HostedWorker(IServiceScopeFactory scopeFactory)
    {
        this.scopeFactory = scopeFactory;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        using (var scope = scopeFactory.CreateScope())
        {
            var database = scope.ServiceProvider
                .GetRequiredService<DatabaseContext>();
            var entity = database.GetSomeEntity();
            scope.ServiceProvider
                .GetRequiredService<ISomeScopedService>()
                .DoSomethingWithTheEntity(entity)
        }
    }
}

public class SomeScopedService: ISomeScopedService
{
    private readonly DatabaseContext context;

    public SomeScopedService(DatabaseContext context)
    {
        this.context = context;
    }

    public void DoSomethingWithTheEntity(SomeEntity entity)
    {
        // the context doesn't track the entity
    }
}

Служба с заданной областью получает контекст базы данных из внедрения зависимости, и оказывается, что это не тот контекст, который я получаю непосредственно от ServiceProvider. В результате контекст БД из области обслуживания не отслеживает сущности, которые я получаю из контекста размещенного сервиса.

Во всех остальных случаях контекст один и тот же: несколько сервисов с областью действия, которые получают базу данных через DI, совместно используют один и тот же контекст, а также, когда я передаю созданную вручную область действия между одноэлементными сервисами, все они получают одинаковые контекст через GetRequiredService. Только когда я пытаюсь смешать, я получаю этот результат.

Есть ли способ получить один и тот же контекст БД во всей области?

UPD Ошибка в конечном итоге не связана с контекстом БД (который действительно одинаков для разных служб в области), но я оставлю вопрос здесь, так как ответ может быть полезен для некоторых другие случаи.

1 Ответ

3 голосов
/ 29 мая 2019

это не тот контекст, который я получаю напрямую от ServiceProvider

Прежде всего, вы никогда не должны получать контекст базы данных напрямую от поставщика услуг.Вы всегда должны получать его в рамках службы, в противном случае вы получите контекст базы данных и соединение, которое не будет сохраняться в течение всего срока службы вашего приложения.

Таким образом, вы всегда должны использовать контексты базы данных внутри службыприцелы.Это делается неявно в конвейере запросов (например, в контроллерах), но в размещенных сервисах вам придется самостоятельно создавать область обслуживания.Вы также должны убедиться, что вы не оставляете эту область открытой в течение длительного периода времени;лучше спроектировать свои службы так, чтобы они обращались к базе данных только в течение очень ограниченного периода времени и имели несколько кратковременных областей обслуживания вместо одной долгоживущей области.

using (var scope = scopeFactory.CreateScope())
{
    var database = scope.ServiceProvider.GetRequiredService<DatabaseContext>();
    var entity = database.GetSomeEntity();
    scope.ServiceProvider.GetRequiredService<ISomeScopedService>()
        .DoSomethingWithTheEntity(entity)
}

Предполагая, что ISomeScopedServiceдолжным образом зарегистрирован как зависимая область, этот код должен разрешать тот же экземпляр контекста базы данных.Контексты базы данных регистрируются как зависимые области (по умолчанию), и, таким образом, это должно разрешить один и тот же экземпляр как от поставщика услуг с областью действия, так и от внедрения конструктора в вашу службу с областью действия.

Если это не работает для вас, то вашреальный код, вероятно, выглядит по-другому, использует другие области (или не имеет областей), или логика, лежащая в основе GetSomeEntity(), возвращает объект без отслеживания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...