更新数据库中的实体时,出现以下异常:
不允许新事务,因为会话中有其他线程正在运行。
我使用相同的代码块来处理所有传入数据(从Excel工作簿中抓取)。可用的INSERT和无效的UPDATE之间的唯一区别如下:
public void UploadWorkbook(Workbook workbook, string uploadedBy, string comments)
{
workbook.UploadedBy = uploadedBy;
workbook.Comments = comments;
var existing = _repository.Get(x => x.FileName == workbook.FileName);
if (existing == null)
_repository.Insert(workbook); // this works on the commit
else
_repository.Update(workbook); // this causes commit to fail
_unitOfWork.Commit(); // fails when repository runs update method
}
另外,这是更新方法:
public override void Update(Workbook entity)
{
var existing = Get(x => x.FileName == entity.FileName);
if (existing == null)
{
var message = string.Format(@"Error :: Cannot update Workbook '{0}'
because it does not exist in the database.",
entity.FileName);
throw new Exception(message);
}
existing.Version = entity.Version;
existing.DateModified = DateTime.Now;
existing.Comments = entity.Comments;
existing.FilePath = entity.FilePath;
if (existing.Data != null)
existing.Data.Clear();
existing.Data = entity.Data;
}
这是Get方法的实现:
public virtual T Get(Func<T, bool> where)
{
return _dbSet.Where(where).FirstOrDefault();
}
我在这里查看了有关类似问题的其他文章,但与我遇到的情况完全不同。我真的被困在这里,因为我对INSERT的工作原理没有多大意义,但是UPDATE失败。
最佳答案
我的第一个怀疑是您的Get电话
Get(x => x.FileName == entity.FileName);
隐式创建在提交工作单元之前未关闭的新线程/事务。然后,您的工作单元将尝试在要提交的调用中创建一个全新的事务,该事务与已经打开的Get()事务冲突。
如果是这种情况,那么您可能想弄清楚如何使Get调用与提交调用在同一事务中进行操作。
编辑:
我相信您只需更改一下就能解决问题
public virtual T Get(Func<T, bool> where)
{
return _dbSet.Where(where).FirstOrDefault();
}
至
public virtual T Get(Func<T, bool> where)
{
return _dbSet.Where(where).SingleOrDefault();
}
SingleOrDefault()
应该强制序列完成“读取”操作,并释放提交事务的连接。 (开始时也可能更安全,因为如果您的查询返回了多个结果,由于未指定任何顺序,因此从FirstOrDefault()
不清楚您实际上将获得哪条记录。使用SingleOrDefault()
会引发异常如果返回多于一行)或者,您可以尝试使用显式事务范围:
public void UploadWorkbook(Workbook workbook, string uploadedBy, string comments)
{
workbook.UploadedBy = uploadedBy;
workbook.Comments = comments;
using (var transaction = new TransactionScope())
{
var existing = _repository.Get(x => x.FileName == workbook.FileName);
if (existing == null)
_repository.Insert(workbook); // this works on the commit
else
_repository.Update(workbook); // this causes commit to fail
_unitOfWork.Commit(); // fails when repository runs update method
transaction.Complete();
}
}
(另请参见Microsoft Connect page on this error message)
关于c# - EF4.1 + MARS-不允许在UPDATE上进行新交易,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7909093/