Параллельные SaveChanges с несколькими объектами - PullRequest
0 голосов
/ 31 октября 2019

В моем основном приложении asp.net у меня есть фоновая служба, которая периодически просматривает БД и обновляет некоторые объекты.

public class Entity
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    [ConcurrencyCheck]
    public int State { get; set; }
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    while (!stoppingToken.IsCancellationRequested)
    {
        try
        {
            foreach (var entity in database.Entities)
                UpdateState(entity);

            database.SaveChanges();
        }
        catch (DbUpdateConcurrencyException e)
        {
            // Yes, well, that's kinda expected
        }
        catch (Exception e)
        {
            // Just in case
        }
        await Task.Delay(10 * 1000, stoppingToken);
    }
}

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

1 Ответ

0 голосов
/ 31 октября 2019

Да. Один из запросов всегда будет успешным, а именно первый. Способ проверки параллелизма работает так, что EF добавляет предложение where в оператор обновления, задавая что-то вроде:

WHERE State = 3

Где значение - это то, что EF знал в последний разоколо. Если другой экземпляр контекста успешно обновил объект, например, теперь State равен 4, то оператор обновления не может ничего сопоставить, и EF выдает DbUpdateConcurrencyException. Если значение совпадает, тогда обновление проходит, как и ожидалось.

Таким образом, ваш блок catch должен реализовывать стратегию восстановления. Как правило, это будет получение последних значений из базы данных, а затем попытка выполнить повторную модификацию сущности оттуда, прежде чем пытаться снова выполнить обновление. Различные стратегии, которые вы можете использовать, а также способы их достижения, подробно описаны в документации.

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