您描述的是标准的concurrency control 问题。在 Web 开发的情况下,通常使用optimistic concurrency control 来解决问题。作为 ASP.NET 开发人员,您可能使用 Microsoft SQL Server 来保存数据。 SQL Server 支持非常有用的数据类型rowversion(也称为timestamp 数据类型)。不可为空的 rowversion 列在语义上等同于 binary(8) 列。使用rowversion 的主要优点是使用简单。 SQL Server 支持与数据库关联的内部计数器。计数器可通过@@DBTS 变量访问。每次修改数据库表中的一行时,rowversion 列将自动更改为@@DBTS 的值,@@DBTS 将递增。可以使用额外的rowversion 列轻松确定该行中的任何值自上次读取以来是否发生了变化。
因此,如果您有一个现有的数据库表,您只需添加一列来保存行更新计数器的行版本(时间戳)。例如语句
ALTER TABLE dbo.Users ADD RowUpdateTimeStamp rowversion NOT NULL
会将rowversion 类型的RowUpdateTimeStamp 列添加到表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)
)
它会创建您描述的表,但该表将具有 rowversion 类型的附加 RowUpdateTimeStamp 列。再次强调,不需要手动在列中保存任何值,这一点很重要。 SQL Server 将自动保存/修改列的值。
如果您使用表中的数据填充网格,例如,您可以将隐藏的RowVersion 列包含在数据库表的RowUpdateTimeStamp 列中的值。 colModel中对应列的定义是这样的
name: "RowVersion", sortable: false, hidden: true, hidedlg: true,
editable: true, editrules: { edithidden: false }
这意味着来自隐藏RowVersion的值将与另一个可编辑列的值一起发送。
修改网格行的服务器方法返回 RowUpdateTimeStamp 的修改版本。我使用inline editing 的aftersavefunc 回调或form editing 的afterSubmit 使用从服务器返回的值修改网格的RowVersion 列。
如果服务器收到来自客户端的修改请求,它总是拥有修改行的RowVersion。服务端代码验证数据库中对应数据的值是否小于或等于
RowUpdateTimeStamp 专栏。如果数据库具有更高的价值,那么 另一个 用户已经修改了数据。如果服务器返回带有一些错误 HTTP 代码 (>=300) 的 HTTP 响应。 jqGrid 将响应解释为错误并显示相应的错误消息。可以使用errorTextFormat 或errorfunc 自定义错误信息。
我在所有生产性实现中都使用上述方法。您可以在the old answer 中阅读有关该主题的更多信息。