Как реализовать оптимистическую блокировку параллелизма с EF 6? - PullRequest
0 голосов
/ 07 ноября 2018

У меня есть вопрос, который смешивает SQL-сервер, Entity Framework и Web API.

Мне нужно управлять базой данных серийных номеров. Для этого я создал таблицу последовательности на своем сервере SQL. Сначала я использую код EF6.

public class Sequence : ITrackingDate
{
    [Key]
    public string Name { get; set; }
    public long CurrentValue { get; set; }
    public long Increment { get; set; }
    public long MinimumValue { get; set; }
    public long MaximumValue { get; set; }
    public bool IsCycling { get; set; }
    public DateTime CreateDate { get; set; }
    public DateTime ModifyDate { get; set; }
}

ITrackingDate используется для обновления моих CreateDate и ModifyDate в текстовом формате EF. Я перезаписываю SaveChange.

Это должно работать как последовательность (как в SQL Server 2012), но я хочу управлять ею самостоятельно в конкретной базе данных, потому что мне нужно будет создать много последовательностей, и большинство из них будет содержать больше данных, чем то, что мы имеем только в система базовых последовательностей. Одна функция, которая мне нужна, - это возможность обновлять последовательность по диапазону.

var serial = context.Sequences.SingleOrDefault(y => y.Name == serialName);
                var firstValue = serial.CurrentValue + 1;
                var lastValue = serial.CurrentValue + range;
                serial.CurrentValue = lastValue;
                context.SaveChanges();

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

Таким образом, метод SaveChanges () должен также проверять, что сохраняемое мной, не является безопасным для другого потока, так как read ().

1 Ответ

0 голосов
/ 07 ноября 2018

Конечно, возможно сделать это безопасным. Во-первых, обратите внимание, что одновременный доступ обязательно должен происходить один за другим. Оптимистический параллелизм здесь не поможет.

Для решения этой проблемы существует две основные стратегии:

  1. Использовать транзакцию RepeatableRead. Это приведет к тупикам, которые вы можете решить, повторив попытку. Повторная попытка безопасна и гарантирует успех.
  2. U-блокировка строки в качестве первого действия в вашей транзакции. Entity Framework не может сделать это напрямую, поэтому вам нужен ручной SQL для этого. Правильные подсказки блокировки: UPDLOCK, HOLDLOCK, ROWLOCK.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...