Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# linq到sql用户并发_C#_Linq To Sql_Concurrency_Winforms - Fatal编程技术网

C# linq到sql用户并发

C# linq到sql用户并发,c#,linq-to-sql,concurrency,winforms,C#,Linq To Sql,Concurrency,Winforms,我目前正在使用linq to sql开发一个C#windows窗体,它从sql表中选择一行,然后允许用户编辑该行中的字段。此表单将一次由多个用户使用,我希望这样,当有人选择了一行并且当前正在表单中输入数据时(一旦用户点击表单上的按钮,该行将被更新),其他人不能选择该行。一旦用户点击按钮执行更新查询,更新的行应再次可选择。基本上,这个过程是: 用户选择行-->其他用户无法选择行-->用户修改行字段值-->用户提交和行更新-->行再次可选择 是否有某种现有功能可用于完成此任务,或者我需要创建一个表来

我目前正在使用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
——更新表格。
更新集locked=1,其中id=@id,locked=0
---返回行计数。
返回@@rowcount
应该注意的是,对“locked”字段的检查非常重要,因为它允许@rowcount值为0或非零(取决于您的ID是否唯一),您可以在应用程序代码的零情况下将其计算为false,在非零情况下计算为true

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

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

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


对于事务和乐观并发,您不必担心这些,因此我再次强烈建议您不要使用非乐观并发模型。

Linq to sql有几种不同的并发选项,但与您描述的不同。在处理保存时,您可以将RefereshMode设置为KeepCurrentValues、OverwriteCurrentValues、KeepChanges,或者在更改时将[UpdateCheck]属性的字段级别的选项设置为Never、Always


您需要编写自己的代码来锁定所引用的记录。另一个选项可能是尝试保存记录,捕获任何并发异常,并询问用户想要做什么(从而设置上面列出的刷新模式)。

默认情况下,LINQ to SQL自行处理并发。当数据更新回数据库时,LINQ to SQL将根据数据库中的当前值检查原始值。如果LINQ To SQL获取的原始值与数据库中的当前值不同,则更新将失败,表明数据已通过其他方式更新。不同的选择是“thekaido”所说的


DataContext
SubmitChanges
方法将抛出一个
ChangeConflictException
,如果该行自LINQ To SQL获取该行以来发生了更改。

这是一个非常旧的线程,但我有一个问题需要回答“当数据更新回数据库时,LINQ to SQL将根据数据库中的当前值检查原始值。如果LINQ To SQL获取的原始值与数据库中的当前值不同,则更新将失败“在什么基础上执行检查。希望与示例进行良好的讨论。谢谢