更新数据库中的实体时,出现以下异常:


  不允许新事务,因为会话中有其他线程正在运行。


我使用相同的代码块来处理所有传入数据(从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/

10-14 14:56
查看更多