我有一个类似的方法:
public async Task SaveItemsAsync(IEnumerable<MyItem> items)
{
using (var ts = new TransactionScope())
{
foreach (var item in items)
{
await _repository.SaveItemAsync(item);
}
await _repository.DoSomethingElse();
ts.Complete();
}
}
Run Code Online (Sandbox Code Playgroud)
这当然有问题,因为TransactionScopeasync/await不能很好用.
它失败并显示InvalidOperationException消息:
"TransactionScope必须放在与它创建的同一个线程上."
我TransactionScopeAsyncFlowOption在这个答案中读到了,这似乎正是我所需要的.
但是,对于这个特定项目,我很难支持.Net 4.0,无法升级到4.5或4.5.1.因此,我的项目中的异步/等待行为由Microsoft.Bcl.Async NuGet包提供.
我似乎无法TransactionScopeAsyncFlowOption在这个或任何其他OOB包中找到.我只是在某个地方错过了吗?
如果没有,是否有其他方法可以达到相同的效果?也就是说 - 我希望事务范围正确完成或回滚,尽管跨越线程有延续.
我DoSomethingElse在上面的示例中添加了说明在事务范围内可能有多个调用,因此在一次调用中简单地将所有项目传递给数据库是不可行的选择.
在它的事项的情况下,库使用直接ADO.Net( ,SqlConnection,SqlCommand等)写入到SQL Server.
UPDATE
我以为我有一个解决方案,涉及从.Net 4.5.1中获取System.Transactions.dll并将其包含在我的项目中.但是,我发现这只适用于我的开发盒,因为它已经安装了4.5.1.部署到仅具有.Net 4.0的计算机时,它不起作用.它只是给了一个MissingMethodException.我正在寻找一种适用于.Net 4.0安装的解决方案.
我正在使用TransactionScope一些批量插入和更新.问题是,即使我将超时设置TransactionScope为一小时,我也会在30分钟的长时间操作中遇到超时异常.
同样在异常之后,它会插入看似随机数量的批次记录.例如,最后一个操作有12440个插入,超时后,表中插入了7673条记录.
的超时SqlConnection和SqlCommand均设置为int.MaxValue.
我究竟做错了什么?
这是我的代码:
using (TransactionScope transaction = new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromHours(1)))
{
try
{
using (db = new DB())
{
//operations here
}
}
catch (Exception ex)
{
throw new Exception("DB Error:\r\n\r\n" + ex.Message);
}
transaction.Complete();
} // <--- Exception here: Transaction aborted (Inner exception: Timeout)
Run Code Online (Sandbox Code Playgroud) 我在数据库中插入记录时遇到错误.
System.Transactions.TransactionException: The operation is not valid for the state of the transaction. ---> System.TimeoutException: Transaction Timeout
--- End of inner exception stack trace ---
at System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction atomicTransaction)
at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification)
at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)
at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
at System.Data.SqlClient.SqlConnection.Open()
Run Code Online (Sandbox Code Playgroud)
实际上我是通过事务范围方法在数据库中插入数据,其代码如下所述.
TransactionOptions tOptions = new TransactionOptions();
tOptions.IsolationLevel = IsolationLevel.ReadCommitted;
tOptions.Timeout = TransactionManager.MaximumTimeout;
using (var transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew, tOptions))
{
}
Run Code Online (Sandbox Code Playgroud)
上述陈述中有什么不正确之处吗?
这里要提到的一点是,我在大量10个表中大量插入数据,包含大量记录,表也允许在批量插入中插入重复记录.用于实现此目的的语法如下所述.
CREATE UNIQUE INDEX …Run Code Online (Sandbox Code Playgroud)