Глобальный замок и жди если что то правда - PullRequest
0 голосов
/ 04 октября 2019

У меня проблема с тем, что мой API получает ColumnId извне (его цель - сделать некоторые обновления в базе данных). Однако, если два запроса с одинаковым Id пытаются получить к нему доступ, я получаю сообщение об ошибке, поскольку две транзакции не могут быть выполнены в одной и той же строке.

Поскольку мне все же необходимо выполнить обе эти функции, есть ли способсоздать класс Singleton или статический класс, который будет обрабатывать эти HTTP-запросы, чтобы в случае отправки API двух запросов с одинаковым ColumnId API выполнял первый, а затем второй?

public MyClass DoStuff(MyClass2 obj, HttpRequestMessage request)
{
    MyClass test = new MyClass();
    // .Create() creates a session with the database
    using (var sc = _sessionManager.Create())
    {
        try 
        {
            var anotherObj = _repository.FindForUpdate(obj.Id);

            //modify anotherObj, save it to the database and set some values for `test` based on anotherObj
        }
        catch
        {
            sc.Rollback();
        }
    }
    return test;
}

FindForUpdate выполняет запрос, подобный следующему:

SELECT * FROM table WHERE id = @Id FOR UPDATE

Лучшее, что я могу придумать, это иметь синглтон (как указано выше), который поставит в очередь и заблокирует using statement в DoStuff, еслиИдентификатор тот же, но я не знаю, как это сделать.

1 Ответ

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

Должно быть довольно просто реализовать глобальную блокировку либо в статическом классе, либо в классе, определенном с единичным временем жизни в вашем контейнере IoC. Для этого можно использовать ключевое слово lock или один из множества других примитивов синхронизации, предлагаемых .Net, например класс SemaphoreSlim.

Однако, как указал Джон, это плохо масштабируется до несколькихвеб-серверы и не использует механизмы параллелизма, предлагаемые базой данных. Трудно дать конкретные рекомендации, не зная специфики вашей платформы базы данных и структуры доступа к данным, но вам, вероятно, стоит рассмотреть либо использование FOR UPDATE WAIT, если ваша база данных поддерживает это, либо просто оптимистический механизм параллелизма с некоторой логикой повторения в вашем приложении дляПовторное применение обновления после небольшого ожидания.

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

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