当我更新数据库中的实体时,我收到以下异常:
不允许使用新事务,因为会话中还有其他线程在运行。
我使用相同的代码块来处理所有传入的数据(从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失败了......如果有另一个事务发生不会导致任何一个动作失败?
答案 0 :(得分:3)
我的第一个怀疑是你的接听电话
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();
}
}