【发布时间】:2016-05-04 03:48:39
【问题描述】:
我有一个要同时执行的事务,当存在给定引用的条目时,我必须更新数据,否则我必须创建一条记录并相应地设置引用。到目前为止,我的代码是这样的:
using (var context = new MyDbContext())
{
using (var scope = context.Database.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))
{
try
{
MyModel model = null;
int hasEntry = context.MyModel.Where(x => x.refID == refID).Count();
if (hasEntry == 0)
{
model = new MyModel();
model.refID = refID;
}
else
{
model = context.MyModel.Where(x => x.refID == refID).Single();
}
// process model object...
if (hasEntry == 0)
{
context.MyModel.Add(model);
}
else
{
context.Entry(model).State = EntityState.Modified;
}
context.SaveChanges();
scope.Commit();
}
catch(Exception)
{
scope.Rollback();
}
}
}
当两个(或更多)实例运行第一个实例时,插入但随后的实例不会更新。他们抛出一个 DBUpdateException 抱怨违反了 PK。
我不知道为什么那些必须更新的实际上是在尝试插入。他们得到一个已经添加到表中的 ID,因此他们抛出了异常。
AFAIK IsolationLevel.ReadCommitted 应该锁定行并在事务完成时释放它们。根据文档 (https://msdn.microsoft.com/en-us/library/cc546518.aspx) “如果您的连接使用已提交的读取隔离级别,并且 SQL Server 在执行 DML 语句时遇到脏行,它将等到当前拥有该行的事务已提交或回滚在继续执行之前。”
所以,我想我有一个脏读,因为实例没有等待首先插入的实例,所以他们尝试插入(使用已使用的 id)并且出现 PK 违规。
我错过了什么?
PD:这是我第一个使用 c# 和 entityframework 的项目。查了很多都没找到答案,如果问题有点傻,请见谅。
【问题讨论】:
标签: c# asp.net entity-framework