【发布时间】:2014-12-13 11:50:15
【问题描述】:
我在 WPF 胖客户端应用程序上使用 EF6.1 和 SQL Server,默认情况下,我使用我实例化的每个 DbContext 打开一个事务(除非另有说明,我提交它并在每个 SaveChanges() 上重新打开它) .这些事务的隔离级别是 READ COMMITED (IsolationLevel.ReadCommited)。
默认情况下,我会在每个“主视图”上打开一个新上下文(因此是一个新事务)。该应用程序是一种假 MDI 应用程序,每个 MDI 视图都将使用自己的DbContext...“主视图”(每个 MDI 选项卡/窗口)可以包含其他辅助视图(想想用于特定数据输入的小模式窗口和类似的东西)将共享与在主视图中打开的相同的上下文(和事务)。我正在使用像UseCase -> Views -> ViewModels 这样的结构...通常“UseCase”会打开一个DbContext 并且可以生成多个视图,这些视图将共享它。这些次要视图通常调用SaveChanges() 而不提交事务,这就是为什么我希望将它们放在首位。
我在实验室服务器上对单个用户进行了一些性能测试,似乎在实例化上下文时打开事务或根本没有事务(其他而不是默认在SaveChanges() 上打开一个 EF)。
我不是 SQL Server 专家,所以我想知道在具有该隔离级别的 SQL Server 上打开许多长时间运行的事务是否有任何影响(当生产服务器上的多个用户使用该应用程序时) (我了解可能锁定读取的其他隔离级别的含义,但事实并非如此)。我在提交事务时手动处理并发错误。
我在这里做的事情是否正确,我应该坚持短期交易,还是只是偏好问题?
我一直在努力寻找答案,但没有找到任何确定的答案(有些人说长期交易不是一个好主意,但他们似乎没有解释原因)。
【问题讨论】:
-
由于锁定和回滚情况下的待办事项量,事务应该尽可能短地打开。事务运行多长时间?
-
为什么次要视图必须调用
SaveChanges?在我看来,视图之间共享的上下文收集了所有更改,因此您可以在现在提交事务的那一刻进行一次SaveChanges调用。 -
@GertArnold ,嗯,这些辅助视图接收一个上下文(可能是通过 DI 新建的,或者传入的),因此它们对正在编辑的实体进行更改,并在完成后调用 SaveChanges。此过程可能是更大更改的一部分(如果用户在主视图上取消,可能需要回滚)或者可能是全新上下文中的独立版本......视图没有意识到这一点,它只是调用 SaveChanges当它完成编辑时。我可以向视图传递一个参数,说明它是否应该保存更改,但我发现事务更优雅且更准确。
-
好的,我明白了。但我不会说持久无知的应用程序代码中的事务管理比在封装数据库事务的工作单元(可能是上下文)中收集更改更优雅。我宁愿寻找在一个用例中涉及的视图之间共享工作单元的方法。一些 IoC 容器可以将组件的生命周期绑定到对象图中聚合根的生命周期(即主视图 + 子视图)。
-
我当然过于简单化了,我正在传递我所谓的“ServiceTransaction”,其中包含一个 UoC(我的 dbcontext 实际上是 UoC),并且我使用服务进行访问。我可能只是跟踪我的更改或传递实体(而不是上下文),但我觉得概念上交易正是我所需要的......直到这个精确的主题进入我的脑海,我质疑是否这是正确的做法。
标签: c# sql-server entity-framework transactions