Обработка ошибок / проблем перед выдачей SaveChanges из DbContext с Core EF в моем API - PullRequest
0 голосов
/ 05 сентября 2018

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

Вот мой код, и тогда у меня было три вопроса:

   [HttpPost]
    public async Task<ActionResult> Post(CreateGroupDto createGroupDto)
    {
     //See if this group exists yet (todo: move to action filter)
     var existingGroup =  _dbContext.Groups.SingleOrDefaultAsync(g => g.Name.ToLower() == createGroupDto.Name.ToLower());

     //The group name isn't taken yet, so create this group
     if (existingGroup == null)
     {
       var user = await _dbContext.Users.FindAsync(GetClaimsUserId());
       var group = _mapper.Map<CreateGroupDto, Group>(createGroupDto);

       //Add the Group  LINE A
       await _dbContext.Groups.AddAsync(group);

       //Add the user as admin of this group  LINE B
       await _dbContext.UserGroups.AddAsync(new UserGroup { .. values set here ..} );

       //Now that everything is added, save changes
       //LINE C
       await _dbContext.SaveChangesAsync();

       return Created("/api/groups/", group.Id);
      }
      else 
         return BadRequest();
    }

Хотя этот код работает для меня нормально, я бы хотел избежать вызова SaveChangesAsync (), если что-то пойдет не так и нужно просто обратиться к следующему:

Вопрос № 1 Если строка A запускается, то в ПАМЯТЬ dbContext добавляет новую группу

Если строка B запускается, то в ПАМЯТЬ dbContext добавляет новую группу пользователей

Когда запускается строка C, она сохраняет оба в базе данных, и если с любым из них возникает исключение, тогда откатывается ВСЕ транзакции (ничего не остается в частичном состоянии) и ошибка 500 возвращается к вызывающему API. Это как если бы никаких данных не было сохранено.

Вопрос № 2 Можно ли вызывать SaveChanges в самом конце, когда все настроено? Я мог видеть, как это контекстно - иногда я хочу сохранить, чтобы увидеть, сработало ли это, прежде чем добавлять что-то еще, а иногда я хочу сохранить, чтобы добавить все одновременно. Многие говорят, что DbContext - это UOW, поэтому в этом случае, если я сохраню транзакции в строке A, а затем снова сохраню в строке B, как мне откатиться?

Вопрос № 3 Я мог видеть, как было бы полезно обернуть все это в блок try..catch, однако мне интересно, если это необходимо - я мог бы добавить некоторый глобальный фильтр исключений, чтобы просто вернуть дружественное сообщение, но строго с точки зрения состояния транзакции, следующее точное (а если нет, есть ли у вас рекомендации действовать более адекватно / разумно):

Мне не нужно обязательно обрабатывать связанные с базой данных исключения в каждом отдельном действии каждого контроллера, потому что в конце концов ошибка приведет к тому, что DbContext автоматически откатит все (если я не вызываю SaveChanges несколько раз, так как упоминается в моем вопросе № 2).

Спасибо!

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