代码之家  ›  专栏  ›  技术社区  ›  monty

实体框架核心:读取和删除数据之间的事务

  •  0
  • monty  · 技术社区  · 7 年前

    我在.NET核心RESTAPI中遇到了实体框架核心的问题。

    数据模型示例:

    会议室(id、houseId、name)

    一个房子可以有多个房间,一个房间只能在一个房子里。

    我的问题发生在我删除一个房间时。每次用户请求删除一个房间时,我都会检查这个房间是否是房子里的最后一个房间,如果是最后一个房间,我也会删除这个(空的)房子。

      Room room = dbContext.Room
        .Include(r => r.House).ThenInclude(h => h.Rooms)
        .Where(r => r.id == id)
        .SingleOrDefaultAsync();
    
      if (room.House.Rooms.Count > 1) {
        // other rooms are present
        dbContext.Room.Remove(room);
      } else {
        // delete house if it is the last room
        dbContext.House.Remove(room.House);
      }
    
      dbContext.SaveChanges();
    

    问题是,我们的UI不会在一次调用中删除一个房子,它会为房子中的每个房间调用delete room(并期望房子与最后一个房间一起自动删除)。这就产生了问题。每个房间加载房屋实体,检查它是否是最后一个房间,识别其他房间,删除房间,保留空房子。

    这是否有可能通过交易等方式解决(这样空置的房子就不会保留)?

    2 回复  |  直到 7 年前
        1
  •  1
  •   TomTom    7 年前

    是和否。你可以把它包装成一个事务-这是微不足道的。

    https://docs.microsoft.com/en-us/ef/core/saving/transactions

    展示如何。

    或者,可以在DbConnection上使用DbTransaction。相同的链接。

    每个房间加载房屋实体,检查它是否是最后一个房间,并识别其他房间 房间,房间被删除,空房子仍然存在。

    听起来像是有人把数据库完全抽象到了那些漂亮的存储库反模式后面——而这(不是事务)现在又回来咬你了。很可能每个被删除的文件室都使用一个单独的存储库,而bum、事务则没有帮助。

    重构时间。

        2
  •  0
  •   peter.edwards    7 年前

    最好的解决方案可能是创建一个新的单独的方法来删除house,该方法在一次调用中处理所有事情。

    如果确实有一些问题阻止您完成DeleteHouse方法,您可以通过锁定来解决问题。我认为你的根本问题是一个线程的比赛条件。为删除房间代码添加一个锁以解决该问题。

    lock(_deleteRoomLock) 
    { \\Your delete room code }
    

    这种模式的缺点是,在删除文件室的服务器端代码中会产生相当大的瓶颈。

    https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement

    推荐文章