4

我目前有一种方法可以读取数据以确定是否需要更新,然后将更新推送到数据库(依赖注入)。该方法受到了很大的打击,我发现了与并发相关的错误,即多次更新,因为多个线程在第一次更新之前读取数据。

我用锁解决了这个问题,效果很好。我怎样才能使用 TransactionScope 来做同样的事情?我可以吗?它会像锁一样阻塞另一个线程吗?此外,我可以像使用锁一样“锁定”一个特定的“id”吗(我保留一个字典,存储一个要为每个 id 锁定的对象)?

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

4

1 回答 1

2

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

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

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

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

于 2013-03-05T19:10:30.970 回答