EF4.1 + MARS -更新时不允许新事务
本文关键字:新事务 事务 不允许 MARS 更新 EF4 | 更新日期: 2023-09-27 18:12:25
当我在数据库中更新一个实体时,我得到以下异常:
不允许新事务,因为会话中有其他线程正在运行。
我使用相同的代码块来处理所有传入的数据(从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);
隐式创建一个新的线程/事务,该线程/事务在提交工作单元之前不会关闭。然后,您的工作单元试图在commit调用中创建一个全新的事务,该事务与已经打开的Get()事务冲突。
如果是这种情况,那么你可能想弄清楚如何让你的Get调用和你的commit调用在同一个事务中操作。
编辑:我相信你可以通过修改
来解决你的问题。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页面关于此错误消息)