Zig*_*giZ 7 sql-server sql-server-2005 multi-user
我真的不想在这里重新发明,所以我要求在多用户数据库应用程序中实现简单(行)锁机制的想法.
假设我有一个表Products,当然它有一个ID(PK),还有一个rowversion列(到目前为止还没有使用),我想只允许一个用户编辑一个特定的行.
当此用户正在编辑记录时(在"签入"之后),其他用户只能查看此记录(只读),但不能修改或删除它.当用户完成并保存记录("结账")时,该记录将再次可供其他用户编辑/删除.
我有一些想法(例如添加"状态"列,或者可能创建一个"锁定"表),但是如果"锁定用户"长时间保持记录(也就是说他去了周末,他的电脑在编辑模式下打开).如果程序在客户端机器上崩溃/系统断电,如何解锁记录......
我想知道是否有一个好的和相对简单的模式(可能包括SQL-Server功能)?
顺便说一句,我的客户端应用程序是Delphi/ADO(不是它非常相关).
我在应用程序中实现的一个简单的解决方案......
CREATE TABLE RecordLocks(
[RecordId] [varchar](8) NOT NULL,
[UserName] [varchar](100) NOT NULL,
[datetimestamp] [smalldatetime] NOT NULL,
[PC] [varchar](100) NOT NULL
)
GO
Run Code Online (Sandbox Code Playgroud)
datetimestamp默认值为GetDate() RecordIda,VARCHAR因为我锁定的表中的主键(不是我的选择)。该表也有明显的索引
CREATE PROCEDURE usp_LockRecord @RecordId VARCHAR(8), @UserName VARCHAR(100), @ComputerName VARCHAR(100)
AS
BEGIN
BEGIN TRAN;
DELETE FROM RecordLocks WHERE DATEDIFF(HOUR, datetimestamp, GETDATE()) > 2;
IF NOT EXISTS (Select * from RecordLocks WHERE RecordId = @RecordId)
INSERT INTO RecordLocks (RecordId, username, PC) VALUES (@RecordId, @UserName, @ComputerName);
Select * from RecordLocks WHERE RecordId = @RecordId;
COMMIT TRAN;
END
GO
Run Code Online (Sandbox Code Playgroud)
首先删除超过2小时的记录(根据需要进行更改)
检查是否没有记录已锁定要锁定的记录,如果没有则插入锁。
选择我们感兴趣的 RecordId 的记录。
然后在调用代码中检查是否已经锁定成功。如果select返回的用户名和PC匹配,则说明刚才传入的数据锁成功。如果用户名匹配但 PC 不匹配,则同一用户会在另一台计算机上打开记录。如果用户名不匹配,则其他用户已将其打开。如果 IE 不成功,我会向用户显示一条消息此记录当前已被工作站 XYZ 上的 JoeB 锁定。
当用户保存记录或离开时,只需删除记录锁即可。
我确信还有其他方法,但这对我来说很有效。
更新
仅当记录不存在时才会插入。以下选择将返回一条记录。如果用户名和/或电脑与您尝试插入的数据不同,则该记录已被另一个用户(或不同计算机上的同一用户)锁定。所以一通电话就可以解决所有问题(可以这么说)。因此,如果我拨打电话Exec usp_LockRecord(1234, 'JoeB', 'Workstation1')并且返回的记录与该数据匹配,我就成功锁定了该记录。如果我取回的用户名和/或电脑不同,则记录已被锁定。然后,我可以向用户显示一条消息,建议记录已锁定,将字段设置为只读,禁用保存按钮,并告诉他们谁拥有该记录的锁定(如果我愿意)。
| 归档时间: |
|
| 查看次数: |
3993 次 |
| 最近记录: |