C# 实体框架下的并发编辑
我已经实现了一个用于并发实体编辑的锁定实体方法(用户在锁定它之前不能开始编辑)。有关锁定实体的信息存储在表中 下面是实现锁定的代码C# 实体框架下的并发编辑,c#,sql-server,entity-framework,C#,Sql Server,Entity Framework,我已经实现了一个用于并发实体编辑的锁定实体方法(用户在锁定它之前不能开始编辑)。有关锁定实体的信息存储在表中 下面是实现锁定的代码 public virtual ObjectLockInfo Lock(int id) { using (var context = DataContextFactory.GetContext()) { var i = context.Object
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
};
}
}
这段代码有一个问题:如果我们在执行context.SaveChanges()
之前收到另一个锁请求(并且它通过了Any
条件),我们将在表上获得两个锁
如何避免它(不使用而不是INSERT
触发器) 使用具有的事务,这将防止您所关心的“幻影行”
public virtual ObjectLockInfo Lock(int id)
{
using (var context = DataContextFactory.GetContext())
using (var dbContextTransaction = context.Database.BeginTransaction(IsolationLevel.Serializable))
{
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();
dbContextTransaction.Commit();
return new ObjectLockInfo
{
Id = lockLock.ID,
IsLocked = true,
LockDate = lockLock.LockObjectDate,
LockExpireDate = lockLock.LockExpireDate
};
}
}
现在,一旦执行了Any
,在您提交更改之前,其他写入程序将无法写入表中(如果自己的事务是read committed
或更高版本,则读卡器将从表中读取)