TransactionScope不能与linux上的async / await方法一起使用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TransactionScope不能与linux上的async / await方法一起使用相关的知识,希望对你有一定的参考价值。

我正在开发一个基于asp.net核心mvc的博客项目,并尝试在ubuntu 16.04 LTS x86-64上部署我的项目。

在将对象插入sql server时使用transactionScope和dapper时遇到了空引用异常。

SQL Server版本为:12.0.4100.1在Windows 2012SP1系统上运行。并且代码在Windows 10(OS Build 17074.1002)上正常运行。但是当我将项目部署到Ubuntu时,它会抛出空引用异常。

异常细节如下:

{System.NullReferenceException:对象引用未设置为对象的实例。 System.Data.ProviderBase.DbConnectionPool.DeactivateObject(DbConnectionInternal obj)处于System.Data.ProviderBase.DbConnectionInternal.CloseConnection(DbConnection owningObject,DbConnectionFactory connectionFactory)的System.Data.ProviderBase.DbConnectionPool.PutObject(DbConnectionInternal obj,Object owningObject)处的System.Data.ProviderBase.DbConnectionPool.DeactivateObject(DbConnectionInternal obj) System.Data.SqlClction.SqlConnection.Close()中的.Data.SqlClient.SqlConnection.CloseInnerConnection()位于Dapper.SqlMapper.d__64 1.MoveNext()位于C: projects dapper Dapper SqlMapper.Async.cs:line 1191 ---抛出异常的前一个位置的堆栈跟踪结束---在System.Runtime.CompilerServices上的System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)的System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()处System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd上的.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)(任务任务) 在System.Runtime.CompilerServices.TaskAwaiter 1.GetResult()at /anome.NiChiJou.Repository.Dapper.BaseDapperRepository 1.d__22.MoveNext()in /home/alex/Documents/Github/Autyan.NiChiJou/src/Autyan.NiChiJou。 Repository.Dapper / BaseDapperRepository.cs:第167行---抛出异常的前一个位置的堆栈跟踪结束---在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess上的System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()处System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd上的System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)的任务任务(任务任务) 在System.Runtime.CompilerServices.TaskAwaiter 1.GetResult()at /anome.NiChiJou.Repository.Dapper.LongKeyDapperRepository 1.d__1.MoveNext()in /home/alex/Documents/Github/Autyan.NiChiJou/src/Autyan.NiChiJou。 Repository.Dapper / LongKeyDapperRepository.cs:第23行---从抛出异常的先前位置开始的堆栈跟踪结束---在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess上的System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()处System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd上的System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)的任务任务(任务任务) 在System.Runtime.CompilerServices.TaskAwaiter 1.GetResult()at /home/alex/Documents/Github/Autyan.NiChiJou/src/Autyan.NiChiJou.Service中的Autyan.NiChiJou.Service.Blog.ArticleService.d__10.MoveNext() .Blog / ArticleService.cs:第39行}

抛出异常的代码是这样的:

using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
    var create = await ArticleRepo.InsertAsync(article);
    if (create <= 0)
    {
        return Failed<Article>("create article failed");
    }
    create = await ContentRepo.InsertAsync(new ArticleContent
    {
        ArticleId = create,
        Content = content
    });
    if (create <= 0)
    {
        return Failed<Article>("create articleContent failed");
    }
    scope.Complete();
}

我试图删除transactionScope,之后,我的代码运行得很好

新代码如下:

var create = await ArticleRepo.InsertAsync(article);
if (create <= 0)
{
    return Failed<Article>("create article failed");
}
create = await ContentRepo.InsertAsync(new ArticleContent
{
    ArticleId = create,
    Content = content
});
if (create <= 0)
{
    return Failed<Article>("create articleContent failed");
}

我用错误的方式使用trancsationScope吗?或者它只是来自dotnet核心本身的错误?

答案

这是因为当等待结束时,分配给继续执行await之后的语句的线程已经丢失了原始执行线程所具有的事务上下文。

将您的Txn范围定义为:

using (var scope = new TransactionScope(..., TransactionScopeAsyncFlowOption.Enabled))

以上是关于TransactionScope不能与linux上的async / await方法一起使用的主要内容,如果未能解决你的问题,请参考以下文章

小巧玲珑和交易范围?

TransactionScope 与 SQLite 内存数据库和 NHibernate

将 TransactionScope 与实体框架 6 一起使用

.Net Oracle TransactionScope的使用

如何在多实例应用程序上处理 TransactionScope?

TransactionScope 是如何工作的?