TransactionScope而不是使用锁

时间:2013-03-05 16:34:35

标签: c# entity-framework-5 transactionscope

我目前有一个方法,它读取数据以确定是否需要更新,然后将更新推送到数据库(依赖注入)。该方法非常困难,我发现并发相关的错误,即多次更新,因为几个线程在第一次更新之前读取数据。

我使用锁解决了这个问题,它运行得非常好。我怎样才能使用TransactionScope来做同样的事情呢?我可以吗?它会阻止另一个线程作为锁吗?此外,我可以锁定一个特定的“id”,因为我正在使用锁(我保留一个字典,存储一个对象以锁定每个id)?

我正在使用Entity Framework 5,虽然它被存储库和工作单元模式隐藏。

1 个答案:

答案 0 :(得分:2)

应用程序级锁定可能不是此问题的解决方案。首先,您通常只需要锁定单个记录或记录范围。接下来,您可能需要锁定其他修改并进入相当复杂的代码。

这种情况通常用乐观或悲观的并发处理。

  • 乐观并发 - 您将拥有额外的数据库生成列(数据库通常具有特殊类型,如timestamp或rowversion)。每次更新记录时,数据库都会自动更新该列。如果将此列配置为行版本,EF将在update =>的where条件中包含该列。执行的更新将使用给定的密钥和行版本搜索记录。如果找到记录,它将被更新。如果未找到记录,则意味着具有密钥的记录不存在或者其他人已经更新了记录,因为当前进程加载了其数据=>您将获得异常,您可以尝试刷新数据并再次保存更改。此模式对于未更新太多的记录非常有用。在你的情况下,它可能会导致另一个麻烦。
  • 悲观并发 - 此模式使用数据库锁定。查询记录时,您将锁定它以进行更新,因此没有其他人也可以将其锁定以进行更新或直接更新。不幸的是,这种模式目前在EF中没有直接支持,你必须通过原始SQL执行它。我写了article explaining the pessimistic concurrency及其在EF中的用法。即使是悲观的并发可能也不是重负载下数据库的好解决方案。

如果您真的构建了一个解决方案,其中许多并发进程会一直尝试更新相同的数据,您可能最终会重新设计,因为没有基于锁定或重新运行失败更新的可靠的高性能解决方案。