更新(2010-12-21):根据我一直在做的测试完全重写了这个问题.此外,这曾经是一个POCO特定的问题,但事实证明我的问题不一定是POCO特定的.
我正在使用Entity Framework,我的数据库表中有一个时间戳列,应该用于跟踪乐观并发的变化.我已将实体设计器中此属性的并发模式设置为"已修复",并且我得到的结果不一致.以下是几个简化的场景,它们演示了并发检查在一个场景中工作但在另一个场景中不起作用.
成功抛出OptimisticConcurrencyException:
如果我附加一个断开连接的实体,那么如果存在时间戳冲突,SaveChanges将抛出一个OptimisticConcurrencyException:
[HttpPost]
public ActionResult Index(Person person) {
_context.People.Attach(person);
var state = _context.ObjectStateManager.GetObjectStateEntry(person);
state.ChangeState(System.Data.EntityState.Modified);
_context.SaveChanges();
return RedirectToAction("Index");
}
Run Code Online (Sandbox Code Playgroud)
不抛出OptimisticConcurrencyException:
另一方面,如果我从数据库中检索我的实体的新副本并对某些字段进行部分更新,然后调用SaveChanges(),那么即使存在时间戳冲突,我也不会得到OptimisticConcurrencyException :
[HttpPost]
public ActionResult Index(Person person) {
var currentPerson = _context.People.Where(x => x.Id == person.Id).First();
currentPerson.Name = person.Name;
// currentPerson.VerColm == [0,0,0,0,0,0,15,167]
// person.VerColm == [0,0,0,0,0,0,15,166]
currentPerson.VerColm = person.VerColm;
// in POCO, currentPerson.VerColm == [0,0,0,0,0,0,15,166]
// in non-POCO, currentPerson.VerColm doesn't change and is still [0,0,0,0,0,0,15,167]
_context.SaveChanges();
return RedirectToAction("Index");
}
Run Code Online (Sandbox Code Playgroud)
基于SQL Profiler,看起来Entity Framework忽略了新的VerColm(这是时间戳属性),而是使用最初加载的VerColm.因此,它永远不会抛出OptimisticConcurrencyException.
更新:根据Jan的要求添加其他信息:
请注意,我还在上面的代码中添加了注释,以便与我在执行此示例时在控制器操作中看到的内容一致.
这是更新前我的DataBase中VerColm的值:0x0000000000000FA7
以下是SQL Profiler在执行更新时显示的内容: …