Лучший способ решить состояние гонки на базе данных

У меня есть приложение, которое сохраняет титры для фильма. Мне нужно предотвратить сценарий, где 2 надписи перекрываются. Сначала я определю, что такое перекрывающиеся титры. Предположим, что класс caption имеет MovieId, EntryTime, ExistTime иText. EntryTime - это число, которое представляет, в какое время (в миллисекундах) в фильм отображается надпись, а ExistTime - время в фильме, где оно исчезнет. Если у нас есть 2 подписи

var caption1 = new Caption(){MovieId = 1, EntryTime = 100, ExistTime =200}
var caption2 = new Caption(){MovieId = 1, EntryTime = 120, ExistTime =220}

Они перекрываются, но следующие подписи не являются

var caption3 = new Caption(){MovieId = 1, EntryTime = 400, ExistTime =450}
var caption4 = new Caption(){MovieId = 2, EntryTime = 425, ExistTime =470}

Все титры для всех фильмов сохраняются в одной базе данных с той же таблицей в базе данных.

Чтобы избежать вставки перекрывающихся титров, я сначала попытаюсь поместить блокировку в свой код сервера. Этот код проверяет специфику EntryTime и EndTime заголовка и не проверяет сценарий перекрытия, но эта проверка должна поддерживать перекрывающийся случай

  lock (insertCaptionLocker)
                    {
                        var captionExists = dbCaptions.Captions.Any(x =>
                                x.MovieId == caption.MovieId && x.EntryTime == caption.EntryTime &&
                                x.ExitTime == caption.ExitTime);

                        if (!captionExists)
                        {

                            dbCaptions.Captions.InsertOnSubmit(caption);
                        }

                        dbCaptions.SubmitChanges();
                    }

У меня есть несколько проблем с этим кодом:

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

Я думаю, что решение должно поступать из базы данных каким-то образом, но я не использую. Любая помощь будет оценена.

c#,sql-server,multithreading,race-condition,

-1

Ответов: 1


0

Наблюдение:

Ваше условие проверяется только в том случае, если для данного MovieId уже существует подпись с такими же EntryTime и ExistTime, она не проверяет, перекрываются ли они.

для неперекрытия вы должны проверить что-то вроде этого, проверяя время начала и окончания для каждой пары:

var non_overlapping = dbCaptions.Captions.Any(x =>
x.MovieId == caption.MovieId &&( x.EntryTime < caption.EntryTime && x.ExitTime < caption.EntryTime || x.EntryTime > caption.EntryTime && caption.ExitTime < x.EntryTime )

Эти пары будут неперекрываться, поэтому вы можете их вставить. С вашим подходом вы получите только те же самые титры, но не все те, которые перекрываются, кулачок ypu также определяет диапазон и проверяет, находится ли ваш кортеж (x.EntryTime ,x.ExitTime)в range(caption.EntryTime ,caption.ExitTime).

C #, SQL-сервер, многопоточный, расы условие,
Похожие вопросы