EF RemoveRange 在事务范围内不起作用
Posted
技术标签:
【中文标题】EF RemoveRange 在事务范围内不起作用【英文标题】:EF RemoveRange not working inside Transaction Scope 【发布时间】:2021-05-24 10:16:15 【问题描述】:我在我们的 ASP.NET MVC 项目中使用 Entity Framework 6.2.0,并且在其中一个操作中,我们使用以下代码从存储库中删除了一系列记录。我们希望这发生在事务范围内,因此发生任何错误都会回滚整个事务。
下面是我的代码 sn-p。如果我删除事务范围但失败,则以下代码可以正常工作。我们在这里使用数据库优先的方法。
using (var tScope = new TransactionScope(TransactionScopeOption.Required))
var boxes= _boxRepository.GetConditionalQuery(s => processId==1).ToList();
if (boxes.Count > 0)
_boxRepository.RemoveRange(boxes);
var boxDeliveries= _deliveriesepository.GetConditionalQuery(s => processId==1).ToList();
_boxDeliveryRepository.RemoveRange(boxDeliveries);
_unitOfWork.Commit();
tScope.Complete();
提前致谢。
【问题讨论】:
你所说的“失败”是什么意思?你有什么例外吗? @AirCodeOne 没有RemoveRanges
。不需要与 EF 或 NHibernate 进行事务。您使用的“存储库”代码破坏了 EF。我们无法告诉您如何修复未发布的代码,但真正的解决方案是简单地删除“通用存储库”代码。仔细阅读There is no need for Unit of Work or Repository with Entity Framework
一个 DbContext 已经是一个工作单元,一个 DbSet 已经是一个存储库。 DbContext 持久化所有更改,并且仅连接到数据库以加载数据或使用SaveChanges
持久化更改。当您调用 SaveChanges
时,它会保留 all 未决更改,而不仅仅是最后一个。您可能需要使用显式事务的唯一原因是您在高级 DbContext 之上放置了一个低级“存储库”接口,在每个操作之后执行SaveChanges
。这破坏了工作单元,所以现在你需要一个额外的事务来恢复它
@AirCodeOne 没有“如果有效”。如果使用得当,EF 可以工作。为什么您认为没有文档教程使用“存储库”模式?微软不知道吗? MS 已经发布模式指南 20 年了,甚至在它变得不必要之前提供了 repo 实现。为什么有这么多关于 "repository" 引发的问题的 EF 相关问题?通用存储库和 ORM 是圆孔的方形钉
@AirCodeOne 这也不是什么新鲜事 Repository is the new Singleton 写于 2009 年。不幸的是,一些“样板”框架和懒惰的作者只是简单地复制粘贴 Java 技术,所以他们可以说它们涵盖了“最佳实践”。通用 repo 所做的不仅仅是破坏 UoW - 它破坏了 DbContext 的断开连接操作和乐观并发,强制执行长期事务,导致阻塞和死锁。通过使用它,您回到了 1999 年,当时引入了断开连接的记录集
【参考方案1】:
请显示您的工作单元和存储库的相关实现代码的实现,人们应该能够提供帮助。在您的数据访问代码之前使用抽象并没有错,就像您应该在您的 UI 代码和其他易失性依赖项之间放置抽象一样。但是,您确实需要很好地了解底层实现代码的工作原理,尤其是如果您要在其上堆叠多个抽象(例如工作单元、存储库)。
GetConditionalQuery 是什么样的? RemoveRange 是什么样的? _unitOfWork 是什么样子的?它从哪里开始或以其他方式引用?
考虑到更多的上下文,您的实现可能会按需要运行。如果您正在寻找 Microsoft 指南来演示如何在架构中使用存储库,请查看此处:
https://github.com/dotnet-architecture/eShopOnWeb https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design为什么 EF 文档中不包含一堆存储库?因为存储库是应用程序抽象,而不是实现。 EF是一种实现。决定如何或是否选择在应用程序及其依赖项之间使用抽象不是他们的责任。因此,EF 文档中没有使用存储库模式并不是他们不推荐该模式的证据。最终我建议他们更喜欢人们直接使用他们的库,因为这让他们的生活更轻松,但他们不负责维护您的应用程序。
更多关于是否通用存储库的辩论(这实际上是一个抽象或非辩论,这实际上是一个 SOLID-or-not 辩论):
https://www.youtube.com/watch?v=FbYYz5i_B_Y&ab_channel=weeklydevtips https://www.youtube.com/watch?v=-O_WVzkLtAA&ab_channel=weeklydevtips https://www.youtube.com/watch?v=_eICIBt5rkw&ab_channel=weeklydevtips祝你好运!
【讨论】:
以上是关于EF RemoveRange 在事务范围内不起作用的主要内容,如果未能解决你的问题,请参考以下文章
UIButton 在 UItableViewCell 内不起作用
扑。列 mainAxisAlignment spaceBetween 在 Row 内不起作用
swift isUserInteractionEnabled = false 在 UITapGestureRecognizer 内不起作用