I really don't want to re-invent the well here, so I'm asking for ideas to implement a simple (row) lock mechanism in a multi-user DB application.
Suppose I have a Table called Products
which of course has an ID (PK), and also a rowversion
column (which is not used so far), and I want to allow only one user to be able to Edit a specific row.
While this users is editing the record (after a "check in"), other users can only View this record (read-only), but not modify or delete it. when the user is done and saved the record ("check out") this record will be again available for editing/deleting by other users.
I have a few ideas (such as adding a "status" column, or maybe create a "lock" table), but there also be considerations if the "locking user" is holding the record for a long time (suppose he went for a weekend and left his computer opened in edit mode). also how to unlock the record if the program crashed/system power down on the client machine...
I was wondering if there is a good and relatively simple pattern for this (which might include SQL-Server features)?
BTW, My client app is Delphi/ADO (not that it's very relevant).
With a timestamp, you can get away with "cheating". The workflow looks something like this:
That should do it.
A simple solution I implemented in an application ....
datetimestamp
has a default ofGetDate()
RecordId
is aVARCHAR
because of the primary key in the table I am locking (not my choice). Also this table has the obvious indexesFirst delete and records older than 2 hours (change to suit)
Check there is no record already locking the the one to lock and if not insert the lock.
Select the record with the RecordId we are interested in.
Then in the calling code check to see if the lock has been successful. If the username and PC coming back from the select matches the data just passed in the lock was successful. If the username matches but the PC doesn't the same user has the record open on a different machine. if the username does not match another user already has it open. I display a message to the user if its unsuccessful I.E This record is currently locked by JoeB on workstation XYZ.
When the user saves the record or navigates away just delete the record lock.
Im sure there are other ways but this works well for me.
Update
A record will only be inserted if one does not exist. The following select will return a record. If the username and/or pc is different to the data you attempt to insert the record is already locked by another user (or same user on a different machine). So one call does all (so to speak). So if I make a call
Exec usp_LockRecord(1234, 'JoeB', 'Workstation1')
and the record I get back matches that data I have successfully got a lock on that record. If the username and/or PC I get back is different the record is already locked. I can then display a message to the user advising the record is locked, make fields read only, disable save buttons and tell them who has a lock on it if I wish.