2

我有一个关于 Jqgrid 行更新的问题。我们有一个如下所示的数据库表。

id :1 field1: john field2:black

想象一下,一个用户想要更新第一行,它有一个名为 id=1 的字段。用户双击该行并打开该行的详细信息。如您所见,第一行 field1 是 john,而 field2 是黑色。例如,如果另一个用户在第一个用户之后双击同一行并将 field2 更新为红色,会发生什么情况?第一个用户仍在更新屏幕上。在他的屏幕上,field2 仍然是黑色的。之后,第一个用户仅将 field1 更新为 jack 并保存该行。结果将是 field1:jack,field2:black。因为第一个用户不知道 field2 的变化。并且第二个用户的 field2 更改已经消失了。在这个例子中如何防止数据丢失?

当用户双击并保存行中的任何更改时,我会更新所有字段。在此先感谢

4

1 回答 1

2

您描述的是标准并发控制问题。在 Web 开发的情况下,通常使用乐观并发控制来解决问题。作为 ASP.NET 开发人员,您可能使用 Microsoft SQL Server 来保存数据。SQL Server 支持非常有用的数据行版本类型(也称为timestamp数据类型)。不可为空的rowversion列在语义上等同于binary(8)列。使用的主要优点是使用rowversion简单。SQL Server 支持与数据库关联的内部计数器。每个@@DBTS变量都可以访问计数器。每次修改数据库表中的一行时,该rowversion列将自动更改的值,@@DBTS并将@@DBTS递增。可以使用附加rowversion列轻松确定自上次读取以来该行中的任何值是否已更改。

因此,如果您有一个现有的数据库表,您只需添加一列来保存行更新计数器的行版本(时间戳)。例如语句

ALTER TABLE dbo.Users ADD RowUpdateTimeStamp rowversion NOT NULL

RowUpdateTimeStamp类型的列添加rowversion到表中dbo.Users。如果您创建新的用户表,您可以执行以下操作

CREATE TABLE dbo.Users (
    Id int NOT NULL IDENTITY,
    FirstName nvarchar(64) NOT NULL,
    LastName nvarchar(64) NOT NULL,
    RowUpdateTimeStamp rowversion NOT NULL,
    CONSTRAINT PK_Users PRIMARY KEY CLUSTERED (Id ASC),
    CONSTRAINT UC_Users_LastName_FirstName UNIQUE NONCLUSTERED (LastName ASC, FirstName ASC)
)

它会创建您描述的表,但该表将具有额外RowUpdateTimeStamp的类型列rowversion。再次强调,不需要手动在列中保存任何值,这一点很重要。SQL Server 将自动保存/修改列的值。

如果您使用表中的数据填充网格,例如,您可以将隐藏列包含在数据库表列中RowVersion的值中。RowUpdateTimeStamp中对应列的定义colModel如下

name: "RowVersion", sortable: false, hidden: true, hidedlg: true,
editable: true, editrules: { edithidden: false }

这意味着隐藏的值RowVersion将与另一个可编辑列的值一起发送。

修改网格行的服务器方法返回修改后的RowUpdateTimeStamp. 我使用内联编辑表单编辑aftersavefunc回调来使用从服务器返回的值修改网格的列。afterSubmitRowVersion

如果服务器从客户端接收到修改请求,它总是RowVersion在修改行。服务器代码验证数据库中相应数据的列值是否小于或相等 RowUpdateTimeStamp。如果数据库具有更高的价值,那么另一个用户已经修改了数据。如果服务器返回带有一些错误 HTTP 代码 (>=300) 的 HTTP 响应。jqGrid 将响应解释为错误并显示相应的错误消息。可以使用errorTextFormaterrorfunc来自定义错误消息。

我在所有生产实现中使用上述方法。您可以在旧答案中阅读有关该主题的其他信息。

于 2013-03-10T20:07:26.030 回答