Можем ли мы применить область транзакции для всех действий API по 1 запросу

#c# #entity-framework #linq #asp.net-web-api

#c# #entity-framework #linq #asp.net-web-api

Вопрос:

Я использую веб-API и EntityFramework 6.2. Планировщик будет вызывать API для каждого идентификатора пользователя. Для одного запроса API выполнит 10 действий. Теперь любое из действий завершается неудачно, эти 10 действий должны быть откатаны для этого конкретного запроса.

Комментарии:

1. Область транзакции имеет дело с транзакциями базы данных. В нем нет понятия HTTP-вызовов.

2. Мой вопрос заключается в том, что в запросе API на 1 CustomerID будет выполнено 10 различных действий с базой данных. Из-за исключения одно действие завершилось неудачно, после чего оно должно отменить ранее выполненные действия

3. Вопрос неправильный. Существует не просто 10 действий с базой данных, это 10 разных подключений к базе данных, при этом 10 разных транзакций выполняют 10 разных команд. Если вы не реализуете протокол распределенных транзакций, невозможно получить 10 разных HTTP-вызовов в рамках одной транзакции. В дни SOAP это ничем не отличалось. Тогда исключением было то, что существовал стандарт для распределенных транзакций, который не масштабировался. Для REST такого стандарта нет

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

5. Если вы хотите, чтобы пакет запросов был завершен только после того, как все они будут получены, вам придется реализовать это самостоятельно — хранить запросы в некотором временном хранилище и фактически вносить какие-либо изменения только при поступлении окончательного запроса. Это означает, что вам нужно добавить вызов, который говорит Start batch , способ соотнести все действия (обычно с идентификатором пакета) и заключительный Finish Batch вызов.

Ответ №1:

Если у вас есть один метод контроллера, который принимает список идентификаторов клиентов, это тривиально. Просто вызовите метод, подобный:

 static void DoStuffToCustomers(List<int> customerIds)
{
    using (var db = new Db())
    using (var tran = db.Database.BeginTransaction())
    {
        foreach (var id in customerIds)
        {
            db.DoStuffToCustomer(id);
        }
        db.SaveChanges();
        tran.Commit();
    }
}
  

Если у вас есть 10 отдельных HTTP-запросов, не рекомендуется даже пытаться.