EF Core 在一个数据库访问中更新多个实体或将它们拆分
Posted
技术标签:
【中文标题】EF Core 在一个数据库访问中更新多个实体或将它们拆分【英文标题】:EF Core updating multiple entities within one database access or split them up 【发布时间】:2022-01-04 10:35:19 【问题描述】:我有权决定以下问题:
2 个对象(即订单和预算,此处简化):
class Order
double Price;
class Budget
double InternalBudget;
double ProjectBudget;
现在是以下问题: 添加新订单时,预算也必须更新。 现在,更好的方法是什么:
在一个数据访问方法中同时进行,例如:
Order SaveOrderAndUpdateRemainingBudget(Order order, budget updateBudget)
// add/update both to DB and dbContext.SaveChanges()
或
Order UpdateOrder(Order order)
// update order
Budget UpdateBudget(Budget budget)
// update budget and dbContext.SaveChanges()
我对第二种方法的看法:如果更新预算失败,我有一个不一致的数据库状态,插入了订单但预算有一个过时的值。
对处理该问题的最佳方式有何建议?
【问题讨论】:
EF 使用事务来确保同时写入所有数据库更新 (ACID)。您需要做的就是确保 SaveChanges/SaveChangesAsync 在所有更新完成后只发生一次。 可能值得考虑使用数据库触发器。 @KieranDevlin - 考虑一个触发器然后尖叫着跑开!我认为它们是邪恶的,几乎在所有情况下都应该避免;几乎总是有更好的方法来做事而不诉诸触发器,当人们没有意识到他们在那里时,这不可避免地会导致问题。将逻辑保留在您的应用中。 @Mog0 这是糟糕的轶事建议。我同意您应该尽可能将业务逻辑保留在数据库之外,但有时从设计、性能和简单性的角度来看这是有意义的。 @KieranDevlin 我的评论是半开玩笑的,但在我构建复杂 Web 应用程序的 20 年中,我发现唯一能更好地使用触发器的是跟踪数据库。我已经删除了许多触发器来整合应用程序逻辑,并且从未有任何性能损失,通常它的性能更好。这是轶事,我确信触发器可以很好地处理某些事情,但我相信这些是例外,通常结构良好的存储库模式可以更好地完成工作。当然其他人会有不同的看法 【参考方案1】:我要做的是像你一样拥有 UpdateOrder 和 UpdateBudget 方法,但它们不会保存在这些方法中。所以你会这样做......
UpdateOrder(order);
UpdateBudget(budget);
dbContext.SaveChanges();
这样,订单被封装在自己的存储库中,而预算在另一个存储库中。 然后保存更改就完成了。
您的选项 2 会产生您所说的问题。
每个实体都应该对自己负责,除非绝对必要,否则对其他实体一无所知。请记住,在理想的世界中,方法应该只做一件事,试着带着它去接近它。
【讨论】:
感谢您的回答!我仍然担心的是,我有一个调用 DataAccess 类以更新/保存实体的协调器类(在可以保存之前处理订单上的操作+触发新预算的计算)。 Coordinator 无权访问 dbContext。所以我仍然需要调用一个方法来执行这两个操作和 dbContext.Save()。我仍然认为它比其他两种方法更干净。 我使用工作单元/存储库模式来解决这个问题,如果你在谷歌上查找它,它会变得干净整洁,微软会在上面发帖。此外,如果有人告诉您工作单元模式是多余的,因为 db 上下文是一个工作单元,那么他们就错了,因为存储库的重点是它可以做一些事情,例如在一个没有的类中记录所有内容触摸服务层(您的协调器类将是服务层)。因此,据我了解,您的 DataAccess 类是这里的存储库,所以您只需要另一层,它是一个工作单元 另外,如果你真的不喜欢工作单元方法,那么如果你使用依赖注入(你应该使用 Ef-core),那么 DbContext 类是有作用域的,因此如果你调用UpdateBudget 方法中的 SaveChanges 但不是 UpdateOrder,它将保存您在 UpdateOrder 中所做的任何更改。但是,我不推荐这种方法,但这取决于你。 看了一下工作单元模式,看起来确实很干净!谢谢!以上是关于EF Core 在一个数据库访问中更新多个实体或将它们拆分的主要内容,如果未能解决你的问题,请参考以下文章
如何在 EF Core 3.1 中使用脚手架流程更新我的实体 - 执行超时已过期
带有 EF Core 更新实体的 ASP.Net 核心 Web Api 如何
EF Core 5.0 - 更新 ASP.NET Core Web API 中的多对多实体