我目前正在使用带有 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/