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

问题描述 投票:0回答:2

我在.NET Core REST API中遇到了Entity Framework Core的问题。

示例数据模型:

表房(id,name)表房(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不会在一个呼叫中删除一个房子,它会为房子中的每个房间调用删除房间(并且期望房子在最后一个房间自动删除)。这导致了问题。每个房间加载房屋实体,检查是否是最后一个房间,识别其他房间,房间被删除,空房子保持不变。

这无论如何都可以解决(所以空房子不会留下来),例如有交易吗?

c# .net-core entity-framework-core
2个回答
2
投票

是的,不是。您可以将其包装到事务中 - 这很简单。

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

说明如何。

你基本上只是创建一个事务:

使用(var transaction = context.Database.BeginTransaction())

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

但是你的代码组织得非常糟糕。

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

听起来有人将这个数据库完全抽象地放在了一些不错的存储库反模式之后 - 而那个(不是交易)现在又回来咬你了。很可能每个被删除的房间都使用一个单独的存储库 - 繁荣,交易无济于事。

重构时间。


0
投票

最好的解决方案可能是创建一个新的单独方法来删除在一次调用中处理整个事情的房子。

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

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

这种模式的缺点是,您最终会在服务器端代码中创建相当大的瓶颈来删除房间。

链接到锁定https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement的文档

© www.soinside.com 2019 - 2024. All rights reserved.