出于诊断原因,我们试图对我们的数据库状态进行一些完整性检查,因此我们将修改的ORM查询包含在TransactionScope中,再加上运行诊断的第二个查询 - 如下所示:
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, _maxTimeout))
{
ORM.DeleteItem();
ORM.CheckIntegrity();
scope.Complete();
}
这是一个手动滚动的ORM,这两个调用最终都会在底部的嵌套事务范围内完成它们的操作。换句话说,当您向下挖掘时,DeleteItem()具有 使用(TransactionScope newScope = new TransactionScope(TransactionScopeOptions.Required,_maxTimeout) {...}
和CheckIntegrity()也有相同的。
在大多数情况下,它一直很好,但我遇到了奇怪的情况。当有人向查询输入一些错误的输入时,DeleteItem()调用可能会抛出异常。该异常在包装器下面的堆栈级别完全捕获并处理。我相信异常也会在之前抛出来嵌套TransactionScope。
但是当我们在CheckIntegrity()调用中进行嵌套作用域创建时,它会从CreateAbortingClone构造函数中抛出“Transaction was aborted error”。内部异常为null。
大多数其他提及CreateAbortingClone交互都与DTC推广(或其失败)有关,内部异常反映了这一点。
我推断CheckIntegrity()调用的中止异常是由于DeleteItem()抛出异常这一事实 - 即使它被吞噬了。
A)是正确的推论吗? TransactionScope对抛出,处理或不处理的任何异常都很敏感吗?
B)有没有办法在进行CheckIntegrity()调用之前检测到它?我的意思是除了重新执行我们的ORM以使异常渗透或添加一些其他全局标志?
由于 标记
答案 0 :(得分:0)
我只知道它如何与EF(实体框架)
一起使用 using (var context = new MyContext(this._connectionString))
{
using (var dbContextTransaction = context.Database.BeginTransaction())
{
}
}
然后,事务链接到上下文。我不是关于你的代码如何建立这种连接的形式,但可能是一些花哨的内置。
然后最好将它包装在try / catch
中try
{
// do-stuff
context.SaveChanges();
//NB!!!!!!
//----------------------
dbContextTransaction.Commit();
}
catch (Exception ex)
{
dbContextTransaction.Rollback();
//log why it was rolled back
Logger.Error("Error during transaction,transaction rollback", ex);
}
所以最终代码看起来像是
using (var context = new MyContext(this._connectionString))
{
using (var dbContextTransaction = context.Database.BeginTransaction())
{
try
{
// do-stuff //
context.SaveChanges();
///////////////////////
//if any exception happen, changes wont be saved unless Commit is called
//NB!!!!!!
//----------------------
dbContextTransaction.Commit();
}
catch (Exception ex)
{
dbContextTransaction.Rollback();
//log why it was rolled back
Logger.Error("Error during transaction,transaction rollback", ex);
}
}
}