我们正在使用Entity Framework并在事务范围内运行单元测试。我们原来在标题中得到了错误。
我设法将问题与某些问题隔离开来。
using (TransactionScope scope1 = new TransactionScope())
{
using (TransactionScope scope2 = new TransactionScope())
{
// Here there is no code
}
using (Entities se = new Entities())
{
EntityConnection entityConnection = (EntityConnection)se.Connection;
DbConnection storeConnection = entityConnection.StoreConnection;
storeConnection.Open(); // On this line the error occurs
// Some code that runs a stored procedure
}
}
我们当前得到的错误是“操作对交易状态无效......”
如果删除事务范围2,一切正常。
如果我将范围2标记为环境事务,它也可以正常工作。
答案 0 :(得分:9)
您创建的scope2没有明确的TransactionScopeOption
参数,默认值为TransactionScopeOption.Required
,请参阅TransactionScope Constructor
此构造函数创建一个新的 事务范围与事务 范围选项等于必需。这个 意味着需要交易 由新的范围和环境 如果已经使用了交易 存在。否则,它会创建一个新的 进入范围之前的交易。
在您的示例中,环境TransactionScope
确实已存在(scope1
),因此具有隐式参数TransactionScope
的新嵌套scope2
(TransactionScopeOption.Required
)是使用现有的环境事务而不是自己创建新事务。
但是,scope2
的隐式事务语义仍然存在,因此scope1
创建的现有环境事务将中止,因为您未在scope2
结束时调用Complete
{1}}:
未能调用此方法会中止 交易,因为交易 经理将此解释为一个系统 失败,或等同于例外 抛出交易范围
当然,如果您删除scope2
或将其语义更改为TransactionScopeOption.RequiresNew
(意味着'始终为范围创建新事务。'),问题会立即消失。 ,因为scope1
创建的现有环境事务不再受影响。
有关详细信息,请参阅Implementing an Implicit Transaction using Transaction Scope。
答案 1 :(得分:0)
这种语法怎么样,这非常相似,Scope2已经完成并稍后处理。
我也间歇地看到“无法访问已处置的对象'交易'错误。 可能是因为我应该使用TransactionScopeOption.RequiresNew而不是TransactionScopeOption.Required创建这两个?
TransactionOptions rootOptions = new TransactionOptions();
rootOptions.IsolationLevel = IsolationLevel.ReadCommitted;
OtherObject.Scope2 = new TransactionScope(TransactionScopeOption.Required, rootOptions);
TransactionOptions options = new TransactionOptions();
options.IsolationLevel = IsolationLevel.ReadCommitted;
options.Timeout = getTransactionTimeout();
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, options))
{
.............
scope.Complete();
}