ASP.NET Core 6+EF Core 6随机抛出事务关联异常求助
约45天前,我将一个基于.NET 5的项目升级到了.NET 6,该项目包含8个网站,均使用ASP.NET Core 6和Entity Framework Core 6,所有网站通过共享配置流程从AWS Parameter Store获取配置。
升级后,随机出现如下异常:
The specified transaction is not associated with the current connection. Only transactions associated with the current connection may be used.
立即重试请求通常能解决问题,但并非每次都有效。我记得在.NET 5、ASP.NET Core 5和Entity Framework Core 5环境下从未出现此类问题,不确定如何解决。以下是我的EF配置代码,是否有人能发现可能的原因?5到6版本间代码并未大幅改动……
public static IServiceCollection AddApplicationDbContextPool( this IServiceCollection services, IConfig config, int poolSize = 1024) { if (config is null) { throw new ArgumentNullException(nameof(config)); } services.AddDbContextPool<ApplicationContext>( _ => { _.UseSqlServer(config.DefaultConnection, __ => { __.UseNetTopologySuite(); if (!config.IsDevelopment) { return; } __.CommandTimeout(int.MaxValue); }); if (!config.IsDevelopment) { return; } _.EnableDetailedErrors() .EnableSensitiveDataLogging(); }, poolSize); services.AddDbContextPool<SerilogContext>( _ => { _.UseSqlServer(config.SerilogConnection, __ => { __.UseNetTopologySuite();// may be unnecessary, but keeping until I verify. if (!config.IsDevelopment) { return; } __.CommandTimeout(int.MaxValue); }); if (!config.IsDevelopment) { return; } _.EnableDetailedErrors() .EnableSensitiveDataLogging(); }); NtsGeometryServices.Instance = new NtsGeometryServices( NetTopologySuite.Geometries.Implementation.CoordinateArraySequenceFactory.Instance, new PrecisionModel(1000d), 4326, GeometryOverlay.NG, new CoordinateEqualityComparer() ); return services; }
后端数据库为SQL Server 2019。升级时更换了数据库服务器,新实例配置更优、硬件性能更强,但我怀疑问题出在应用与数据库的交互而非数据库本身。
其中一个高负载应用使用Dapper操作数据库,以下是Dapper配置,该应用使用Singleton作用域(Transient可移除,已无依赖):
public static IServiceCollection AddApplicationDapper( this IServiceCollection services, IConfig config, ServiceLifetime serviceLifetime = ServiceLifetime.Transient) { if (config is null) { throw new ArgumentNullException(nameof(config)); } SqlMapper.AddTypeHandler(new GeometryHandler<Point>(true)); SqlMapper.AddTypeHandler(new GeometryHandler<Polygon>(true)); return serviceLifetime == ServiceLifetime.Singleton ? services.AddSingleton( _ => new SqlConnection(config.DefaultConnection)) : services.AddTransient( _ => new SqlConnection(config.DefaultConnection)); }
是否可能是应用中广泛使用async/await导致的?我几乎在所有地方都使用了.ConfigureAwait(false),线程切换会不会是原因?这部分在5到6版本间也未大幅改动。
我曾怀疑是EF Core Triggered包导致,已移除该包,但异常仍持续出现,恳请各位提供帮助!
@Dai
关于单例SqlConnection的Dapper使用说明:仅在一个应用中使用,该应用是与其他ASP.NET Core应用统一管理的ASP.NET Core程序,但不处理Web请求,而是作为IoT监听器和处理器,注册了几个单例IHostedServices类。IoT服务监听特定设备的报告,然后传递给处理服务,仅处理服务使用SqlConnection实例,属于一对一使用,因此单例SqlConnection可正常工作,此配置从.NET Core 2.0起一直沿用。
出现异常的并非该项目,而是其他使用EF Core操作数据库的项目。我认为IoT应用中单个处理服务使用的单例SqlConnection并非问题原因。
@Gert Arnold
我99.9991%确定所有异步操作都已使用await,至少ReSharper会在遗漏时提示。
System.InvalidOperationException: The specified transaction is not associated with the current connection. Only transactions associated with the current connection may be used. at Microsoft.EntityFrameworkCore.Storage.RelationalTransaction..ctor(IRelationalConnection connection, DbTransaction transaction, Guid transactionId, IDiagnosticsLogger`1 logger, Boolean transactionOwned, ISqlGenerationHelper sqlGenerationHelper) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerTransactionFactory.Create(IRelationalConnection connection, DbTransaction transaction, Guid transactionId, IDiagnosticsLogger`1 logger, Boolean transactionOwned) at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.BeginTransactionAsync(IsolationLevel isolationLevel, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.BeginTransactionAsync(CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(StateManager stateManager, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken) at REDACTED.App.Devices.Locate.CommandHandler.Handle(Command command, CancellationToken cancellationToken) in E:\Software Development\REDACTED\REDACTED.App\Features\Devices\Locate.cs:line 69
内容的提问来源于stack exchange,提问作者Gup3rSuR4c

