在我的API中通过具有核心EF的DbContext发布SaveChanges之前处理错误/问题

时间:2018-09-04 21:44:22

标签: c# asp.net-mvc entity-framework-core asp.net-core-webapi

我这里有一个控制器,该控制器具有创建组的动作-它写入两个不同的数据库表。如下所示,我正在检查该组是否存在,因此只能有一个具有唯一名称的组,但是如果两个请求同时输入相同的组名,我会看到此代码是错误的,但是我觉得这几率极低。

这是我的代码,然后我遇到三个问题:

   [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行,则在MEMORY dbContext中添加一个新组

如果B行运行,则在MEMORY dbContext中添加一个新的UserGroup

运行C行时,它将两者都保存到数据库中,并且如果其中任何一个发生异常,那么ENTIRE事务都会回滚(部分状态什么都没有保留),并且API的调用者返回500错误。好像没有任何数据保存。

第2个问题 设置完所有内容后,可以立即调用SaveChanges吗?我可以看到它是如何上下文的-有时我想保存一下以查看是否在添加其他时间之前起作用,有时我想保存以同时添加所有内容。许多人说DbContext是一个UOW,因此在这种情况下,如果我将事务保存在A行中,然后再次保存在B行中,该如何回滚?

第3个问题 我可以看到将整个内容包装在try..catch块中将有什么帮助,但是我想知道是否有必要-我可以添加一些全局异常过滤器以仅返回友好消息,但严格来说是在事务状态方面,以下准确信息(如果没有,您是否建议您更适当/明智地进行):

我不必在每个控制器的每个操作中都必须处理与数据库相关的异常,因为最终错误将导致DbContext自动回滚所有内容(除非我多次调用SaveChanges在我的问题2中提到)。

谢谢!

0 个答案:

没有答案