Uma solução simples que implementei em um aplicativo....
CREATE TABLE RecordLocks(
[RecordId] [varchar](8) NOT NULL,
[UserName] [varchar](100) NOT NULL,
[datetimestamp] [smalldatetime] NOT NULL,
[PC] [varchar](100) NOT NULL
)
GO
datetimestamp
tem um padrão de GetDate()
RecordId
é um VARCHAR
por causa da chave primária na tabela que estou bloqueando (não é minha escolha). Também esta tabela tem os índices óbvios 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
Primeira exclusão e registros com mais de 2 horas (alterar para se adequar)
Verifique se não há registro já travando o que deseja travar e se não estiver insira a trava.
Selecione o registro com o RecordId em que estamos interessados.
Em seguida, no código de chamada, verifique se o bloqueio foi bem-sucedido. Se o nome de usuário e o PC retornando da seleção corresponderem, os dados que acabaram de passar no bloqueio foram bem-sucedidos. Se o nome de usuário corresponder, mas o PC não corresponder, o mesmo usuário terá o registro aberto em uma máquina diferente. se o nome de usuário não corresponder outro usuário já o tem aberto. Eu mostro uma mensagem para o usuário se seu I.E não for bem-sucedido. Este registro está atualmente bloqueado por JoeB na estação de trabalho XYZ.
Quando o usuário salva o registro ou navega para longe, basta excluir o bloqueio do registro.
Tenho certeza de que existem outras maneiras, mas isso funciona bem para mim.
Atualizar
Um registro só será inserido se não existir. A seleção a seguir retornará um registro. Se o nome de usuário e/ou pc for diferente dos dados que você tenta inserir o registro já está bloqueado por outro usuário (ou mesmo usuário em uma máquina diferente). Assim, uma chamada faz tudo (por assim dizer). Então, se eu fizer uma chamada
Exec usp_LockRecord(1234, 'JoeB', 'Workstation1')
e o registro que recebo corresponde aos dados que obtive com sucesso um bloqueio nesse registro. Se o nome de usuário e/ou PC que recebo for diferente, o registro já está bloqueado. Eu posso então exibir uma mensagem para o usuário informando que o registro está bloqueado, tornar os campos somente leitura, desabilitar os botões de salvar e dizer a eles quem tem um bloqueio, se eu desejar.