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失败了。如果有另一个事务正在进行,这不会导致任何一个操作失败吗?

EF4.1 + MARS -更新时不允许新事务

我的第一个怀疑是你的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页面关于此错误消息)