c# - linq-to-sql用户并发

标签 c# linq-to-sql concurrency winforms

我目前正在使用带有 linq-to-sql 的 C# windows 窗体,它从 SQL 表中选择一行,然后允许用户编辑该行中的字段。此表单一次将被多个用户使用,我希望拥有它,所以当有人选择了一行并且当前正在表单中输入数据时(一旦用户点击表单上的按钮,该行将被更新) 没有其他人可以选择该行。一旦用户点击按钮执行更新查询,更新的行应该可以再次选择。基本上这个过程是:

用户选择行-->行变得不被其他用户选择-->用户修改行字段值-->用户提交和行更新-->行再次变得可选择。

我是否可以使用某种现有功能来完成此操作,或者我是否需要创建一个表来跟踪哪些行是不可选择的,并让应用程序在选择行之前查询该表(即查询表以查看行是否不可用,如果不插入 rowid 用户正在编辑,则在用户提交更改后删除行)?

最佳答案

您要做的是对您正在访问的资源(在本例中为数据库行)强制实现非乐观并发。

通常,.NET 中的数据模型只支持开放式并发(如果您完全支持并发,那就是),您现在看到的大多数数据库编程都遵循相同的趋势。

也就是说,您可能应该看看乐观并发模型,其中您有某种时间戳(无论是二进制值还是日期,每次更新记录都会发生变化),当你想执行更新操作。

如果 id 和时间戳匹配,操作成功,否则,它通知用户其他人已经更新了记录,应该重新加载数据并尝试再次更新记录。

应该注意的是,这种模式的扩展性比任何非乐观模式都要好得多。

话虽这么说,如果你真的想要一个非乐观的模式,你必须伪造它。

如上所述,.NET 数据提供程序模型不支持非乐观并发。当用户开始操作时,它会检查一个字段(“锁定”或类似的字段)以查看记录当前是否已锁定。如果它被锁定,则不允许用户打开表单修改数据。如果未锁定,则允许用户打开表单并修改数据。

这里有两件重要的事情你必须做。第一种是将“locked”字段设置为 true,表示您有一把锁。

其次是确保在比较值和更新锁定字段时是在一个事务中操作。如果不这样做,则存在两个客户端同时更新该字段的可能性,这是您不希望的。

封装它的最佳方法是使用一个存储过程,该过程采用您要锁定的记录的 ID。

然后它执行更新,如下所示:

--- Update the table.
update <table> set locked = 1 where id = @id and locked = 0

--- Return the rowcount.
return @@rowcount

应该注意的是,对“锁定”字段的检查非常重要,因为它允许@@rowcount 值为 0 或非零(取决于您是否ID 是唯一的),您可以在应用程序代码中在零情况下评估为假,在非零情况下评估为真。

然后,在您的应用程序代码中,您完成交易,如果值为真,您打开表单并允许用户编辑,否则,您通知他们必须等待。

当用户完成保存记录时,他们再次在与其他保存操作的事务中将“锁定”位设置回零。

这样做的一个明显缺点是,如果您的应用程序在用户锁定记录后崩溃,它永远不会解锁,您将不得不手动删除“锁定”位。

有了事务和乐观并发,你不必担心这些,所以我再次强烈建议你不要使用非乐观并发模型。

关于c# - linq-to-sql用户并发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2330004/

相关文章:

Java 7 : best way to implement thread-safe modifiable static object in ServletContextListener?

c# - 关于 32 位 .exe 与 64 位 .exe

c# - 如何在 MVP 中设置控件状态

c# - 如何允许 powershell 从 .net 核心 MVC web 应用程序下载 EXE?

c# - 无法使用 linq2sql 从文本更新表

java - 为什么等待线程不会永远等待

c# - 提供了无效的请求 URI。请求 URI 必须是绝对 URI,或者必须设置 BaseAddress。尝试使用网络服务

linq-to-sql - Linq to SQL 和 SQL 注入(inject)

C#/Linq-to-sql - 锁定 datacontext.Table on insertonsubmit

ruby - 测试并发特性