C# Blazor - 修复“此连接与环境事务一起使用...”

Posted

技术标签:

【中文标题】C# Blazor - 修复“此连接与环境事务一起使用...”【英文标题】:C# Blazor - Fix "This connection was used with an ambient transaction..." 【发布时间】:2019-11-21 09:32:18 【问题描述】:

我在 Blazor 页面中添加了一个计时器,因此某些数据(从数据库中提取)可以每 5 秒刷新一次。当我在页面上时它工作正常,但是当我移动到另一个页面并返回到原来的页面时,我收到了这个错误:

“此连接用于环境事务。原始 环境事务需要在此连接之前完成 在它之外使用”我在末尾包含了堆栈跟踪

我尝试在页面释放时释放 Timer,但没有解决。看起来这个问题是由于数据库上下文是如何在依赖注入容器中注册的,但是

这是我页面的 C# 代码。它调用主服务,后者依次通过存储库获取数据。

@functions 

    protected Dictionary<int, int> RunningTaskProcessQueueCountDictionary;
    protected Dictionary<int, int> PendingTaskProcessQueueCountDictionary;
    protected Timer CountRefreshTimer = null;

    protected override async Task OnInitAsync()
    
        CountRefreshTimer = new Timer(new TimerCallback(async _ =>
        
            await RefreshCount();
            await base.Invoke(StateHasChanged);
        ), null, 0, 5000);
    


    private async Task RefreshCount()
    
        RunningTaskProcessQueueCountDictionary = await mainService.GetRunningTaskProcessQueueCountByTaskAppAsync(null);
        PendingTaskProcessQueueCountDictionary = await mainService.GetPendingTaskProcessQueueCountByTaskAppAsync(null);
    

    public void Dispose()
    
        if (CountRefreshTimer != null)
        
            CountRefreshTimer.Dispose();
        
    

这是注册数据库上下文的 startup.cs 的摘录:

// Register the DB Context
var connection = Configuration.GetConnectionString("SQL01.xxx");
services.AddDbContext<SQL01xxxContext>(options => options.UseSqlServer(connection));

// Register all repositories and services (using Scrutor)
services.Scan(scan =>
    scan.FromAssemblies(typeof(IMainService).Assembly, typeof(ITaskAppRepository).Assembly)
        .AddClasses()
        .AsMatchingInterface()
        .WithScopedLifetime());

services.AddScoped<DbContext, SQL01xxxContext>();
services.AddScoped<IUnitOfWork<SQL01xxxContext>, UnitOfWork<SQL01xxxContext>>();

这是错误的堆栈跟踪

System.InvalidOperationException HResult=0x80131509 消息=此 连接与环境事务一起使用。原始环境 需要先完成事务才能使用此连接 在它之外。来源=Microsoft.EntityFrameworkCore.Relational 堆栈跟踪:在 Microsoft.EntityFrameworkCore.Storage.RelationalConnection.HandleAmbientTransactions() 在 Microsoft.EntityFrameworkCore.Storage.RelationalConnection.d__42.MoveNext() 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable1.AsyncEnumerator.d__12.MoveNext() 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.<ExecuteAsync>d__72.MoveNext() 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable1.AsyncEnumerator.d__11.MoveNext() 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.ConfiguredTaskAwaitable1.ConfiguredTaskAwaiter.GetResult() at System.Linq.AsyncEnumerable.SelectEnumerableAsyncIterator2.d__7.MoveNext() 在 D:\a\1\s\Ix.NET\Source\System.Interactive.Async\Select.cs:106 行 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.ConfiguredTaskAwaitable1.ConfiguredTaskAwaiter.GetResult() at System.Linq.AsyncEnumerable.AsyncIterator1.d__10.MoveNext() 在 D:\a\1\s\Ix.NET\Source\System.Interactive.Async\AsyncIterator.cs:line 112 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor1.EnumeratorExceptionInterceptor.d__5.MoveNext() 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Linq.AsyncEnumerable.d__63.MoveNext() in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\Aggregate.cs:line 120 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() 在 SIQC.Enterprise.GenericRepository.Common.IQueryableExtensions.d__11.MoveNext() in C:\TFS\[...]\IQueryableExtensions.cs:line 28 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() 在 SIQC.Enterprise.GenericRepository.RepositoryBase.ReadOnlyRepository1.<GetAsync>d__12.MoveNext() in C:\TFS\[...]\ReadOnlyRepository.cs:line 174 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() 在 ToolsWebManagementData.IntravexV21.Repository.TaskProcessQueueRepository.d__2.MoveNext() 在 C:\TFS[...]\TaskProcessQueueRepository.cs:第 46 行 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at TWMBlazorSSB.Services.MainService.<GetRunningTaskProcessQueueCountByTaskAppAsync>d__21.MoveNext() in C:\TFS\[...]\MainService.cs:line 79 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() 在 TWMBlazorSSB.Pages.TaskApp.TaskApps.d__7.MoveNext() 在 C:\TFS[...]\TaskApps.razor: 第 91 行 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.GetResult() 在 TWMBlazorSSB.Pages.TaskApp.TaskApps.d.MoveNext() 在 C:\TFS[...]\TaskApps.razor:第 79 行

任何帮助将不胜感激。 谢谢

【问题讨论】:

【参考方案1】:

看起来这个问题是由于数据库上下文是如何注册的

没错。这是因为AddDbContext&lt;&gt; 使用(默认)ServiceLifetime.Scoped。但是没有有用的Scope。

这仍然是under discussion by the Blazor team,也许在考虑解决方法之前等待下一个预览。

但我看到它现在已升级到 preview-9。

【讨论】:

以上是关于C# Blazor - 修复“此连接与环境事务一起使用...”的主要内容,如果未能解决你的问题,请参考以下文章

在 Blazor 中将 HTML 元素的值绑定到 C# 属性

混合 Blazor 组件、DI 和 C# 8 可为空

[Inject] 有问题,不能在 C# 类 (Blazor) 中工作

可以使用 C# 的 Web 前端框架 Blazor

可以使用 C# 的 Web 前端框架 Blazor

可以使用 C# 的 Web 前端框架 Blazor