【问题标题】:How to implement locking across a network如何在网络上实现锁定
【发布时间】:2015-06-06 00:40:18
【问题描述】:

我有一个桌面应用程序。在此应用程序中,用户可以打开和处理许多记录。如果用户单击记录,程序将锁定该记录,因此其他人无法使用它。如果记录已经被锁定,那么用户仍然可以查看它,但它将是只读的。我们本地网络上的许多用户都可以打开和处理记录。

我的第一个想法是使用数据库来管理记录上的锁。但我不确定这如何或是否是最好的方法。我可以使用任何编程模式或现成的解决方案吗?

【问题讨论】:

  • 根据您的描述,使用 TFS 等源代码控制系统是最简单的。但那是因为你的描述不够充分。请提供有关工作流程、数据类型等的更多信息。这仍然是一个过于宽泛的问题,但在问题结束之前您可能会得到一些有用的 cmets。
  • 听起来你想研究实现悲观锁定的方法。这个网站上有很多类似的Q。
  • 您确实想使用 SQL 锁定。 SQL 锁基于隔离级别和 DM 类型。如果没有您的控制,SQL 锁会从 ROW 开始,然后自动升级到页面(每页多行),最终升级到整个表。理想情况下,SQL 锁应该持续几毫秒——而不是人工编辑间隔。有许多可能的模式可以解决用户会话锁定问题 - 但它们取决于各种细节(正如 John Saunders 指出的那样)。
  • 您描述的是悲观锁定,而不是乐观锁定。各有各的用途。由于性能问题,悲观主义通常不受欢迎。然而,它有时是你所需要的。如果这确实是您想要的,您需要让您的 ADO 命令启动 SQL BEGIN TRAN,在整个进程的生命周期内保持相同的连接对象处于活动状态,并且在获取记录时使用 UPDLOCK 提示。
  • 我真的不想在 SQL Server 中锁定记录。我在想也许我可以在表格上创建一个名为“Locked”(布尔)的列。然后,当用户单击记录时,程序将检查 Locked 标志是否为真。如果它为真,那么它将返回真。如果它是假的,那么它将锁定标志设置为真。您发现这种方法有什么问题吗?

标签: c# sql-server wpf


【解决方案1】:

我已经为访问数据库的 WPF 应用程序实现了一个类似的系统,但是我不再可以访问源代码,我将在此处尝试解释。我采取的路线与使用数据库有些不同。使用Duplex WCF service,您可以在客户端连接的某处(即数据库服务器)托管服务。要了解的关键事项:

  • 您可以通过使用某种数据类型并确保每个行类型具有相同类型的主键(例如long)来使此服务通用。在这种情况下,您的签名可能类似于:bool AcquireLock(string dataType, long id),或者如果用户经常修改大量行,则将bool/long 替换为bool[]long[]
  • 在服务器端,您必须能够快速响应此请求。考虑将数据存储在类似于 Dictionary<String (DataType), Dictionary<User, HashSet<long>> 的行中,其中根字符串是一种数据类型。
  • 当某人连接时,他可以接收给定数据类型的所有锁定列表(例如,当打开锁定该类型记录的屏幕时),同时还可以注册以接收给定数据类型的更新。
  • 客户端与服务器之间的套接字连接定义了用户已“连接”。如果套接字关闭,服务器会释放该用户的所有锁,立即通知其他用户该用户丢失了锁,从而使记录再次可供编辑。 (这涵盖了用户断开或终止进程等场景。
  • 为避免并发问题,请确保用户在允许他进行任何更改之前获得了锁。 (例如BeginEdit,首先检查服务器,在您的视图模型上实现IEditableObject)。
  • 当一个锁被释放时,客户端告诉服务器他是否对该行进行了更改,以便其他客户端可以更新相应的数据。当套接字断开连接时,假设没有任何变化。
  • 不错的添加功能:在为用户提供锁列表/更新时,还提供用户 ID,以便人们可以看到谁在做什么。

这种形式的“实时并发”提供了比提供处理乐观并发问题的方法更好的用户体验,并且在技术上也可能更容易实现,具体取决于您的场景。

【讨论】:

  • 这很棒。在您的第二个要点上,字典将在静态类中吗?而且,使用双工服务来通知客户是个好主意。永远不会想到这一点。
  • 我使用的系统非常相似,这是我几年前做的一个项目。另一个很好的功能是通过主键“订阅”文档的能力。服务器保留感兴趣的客户列表,并向他们发送有关他们订阅的内容更改的消息。客户端在以只读方式查看密钥时订阅密钥,并且可以在有人对其进行编辑时立即获取更改。
  • 我们遇到的唯一问题是,有些人会在周末回家时将关键文件锁定。我们最终实现了“超时”,以及管理员从管理屏幕强制释放锁定的能力。
  • 同意@BradleyUffner 提到的超时。我使用了单实例 WCF 服务,因此您可以将其保持在本地状态或改用静态类,使其线程安全,以便您可以允许不同线程上的多个客户端使用它。
猜你喜欢
  • 2012-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-17
  • 2011-08-11
  • 1970-01-01
  • 2020-05-20
  • 1970-01-01
相关资源
最近更新 更多