I've implemented a lock entity method for concurrent entity editing (user can't start editing before locking it). Information about locked entities is stored in table.
Here is the code that implements locking.
public virtual ObjectLockInfo Lock(int id)
{
using (var context = DataContextFactory.GetContext())
{
var i =
context.ObjectLock.Any(
c =>
c.ObjectID == id && (c.ObjectType == (int) _lockObjectType) &&
c.LockExpireDate > DateTime.Now);
if (i)
return new ObjectLockInfo
{
ErrorMessage = "Object is locked",
IsLocked = false
};
var lockLock = new ObjectLock
{
LockExpireDate = DateTime.Now.AddMinutes(20),
LockObjectDate = DateTime.Now,
ObjectID = id,
ObjectType = (int) _lockObjectType,
UserID = _currentUserID
};
context.ObjectLock.Add(lockLock);
context.SaveChanges();
return new ObjectLockInfo
{
Id = lockLock.ID,
IsLocked = true,
LockDate = lockLock.LockObjectDate,
LockExpireDate = lockLock.LockExpireDate
};
}
}
This code has a problem: if we get another lock request before context.SaveChanges() is executed (and it passes Any condition), we will get two locks on the table.
How to avoid it (without using INSTEAD OF INSERT trigger)?