错误 NHibernate.Util.ADOExceptionReporter 请求的操作无法完成,因为连接已断开



我有一个 ASP.NET MVC应用程序,其中nHibernate作为ORM(使用SQL Server作为数据库)。

每 5-6 个请求,就会抛出一个异常,其中包含上述标题所述的随机错误。

这仅在GET请求中发生,并且从以下方面开始:

准备时出错 选择 ..

自从我将 NHibernate 4.x 升级到 NHibernate 5.0.3(现在是 5.1.1)以来,这些问题就开始了。在此过程中,我还更新了目标框架,以前是 .NET 4.5.2,现在是 .NET 4.7.2。

我已经检查了几乎所有内容,确保数据库没有任何连接泄漏或超时,但错误仍然存在。已尝试从连接字符串中关闭"透明网络IPResolution"和"登记"功能 - 问题仍然存在。

关于解决问题的任何想法都将非常受欢迎。

这是导致以下异常的罪魁祸首(部门服务:838):

var department = _departmentRepository.Get(departmentId);

场景如下,我有多个网格,因此针对同一操作触发多个请求。同一页面的每 5-6 次刷新,许多请求中的一个都会失败(失败的一个请求是随机的,即有时是第 1 次,有时是第 2 次,依此类推)。

这是志中的完整异常代码段:

2020-06-26 13:25:16,297 [50] 错误 NHibernate.Util.ADOExceptionReporter [(null)] - 在准备选择department0_时。部门 ID 作为 departmentid1_22_0_,department0_。创建于 createdat4_22_0_,department0_。修改在 作为modifiedat5_22_0_,department0_。名称为 name2_22_0_,department0_。状态为status6_22_0_,department0_。创建者 作为createdby7_22_0_,department0_。修改者 作为modifiedby8_22_0_,department0_。SiteId 作为 siteid3_22_0_ 来自 dbo。部门department0_department0_的地方。部门 ID = @p0发生错误 2020-06-26 13:25:16,298 [50] 错误 NHibernate.Util.ADOExceptionReporter [(null)] - 请求的操作无法完成,因为连接已断开。

2020-06-26 13:25:16,300 [50] 错误 [(空)] - NHibernate.ADOException:在准备选择department0_时。部门 ID 作为 departmentid1_22_0_,department0_。创建于 createdat4_22_0_,department0_。修改在 作为modifiedat5_22_0_,department0_。名称为 name2_22_0_,department0_。状态为status6_22_0_,department0_。创建者 作为createdby7_22_0_,department0_。修改者 作为modifiedby8_22_0_,department0_。SiteId 作为 siteid3_22_0_ 来自 dbo。部门department0_department0_的地方。DepartmentId=@p0 系统--->发生错误。无效操作异常: 请求的操作无法完成,因为连接已断开。

atSystem.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest, String name, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlDelegatedTransaction.Initialize()
at System.Transactions.TransactionStatePSPEOperation.PSPEInitialize(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, GuidpromoterType)
at System.Transactions.TransactionStateActive.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction atomicTransaction, Guid promoterType)
at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Guid promoterType)
at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification)
at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)
at System.Data.ProviderBase.DbConnectionPool.PrepareConnection(DbConnection owningObject, DbConnectionInternal obj, Transaction transaction)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource1 retry)
at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource'1 retry)
at System.Data.SqlClient.SqlConnection.Open()
at NHibernate.Connection.DriverConnectionProvider.GetConnection()
at NHibernate.AdoNet.ConnectionManager.GetConnection()
at NHibernate.AdoNet.AbstractBatcher.Prepare(DbCommand cmd)
--- 结束内部异常堆栈跟踪---

at NHibernate.AdoNet.AbstractBatcher.Prepare(DbCommand cmd)
at NHibernate.AdoNet.AbstractBatcher.ExecuteReader(DbCommand cmd)

at NHibernate.Loader.Loader.GetResultSet(DbCommand st, QueryParameters queryParameters, ISessionImplementor session,IResultTransformer forcedResultTransformer)
at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies, IResultTransformer forcedResultTransformer)
at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies, IResultTransformer forcedResultTransformer) at NHibernate.Loader.Loader.LoadEntity(ISessionImplementor session, Object id, IType identifierType, Object optionalObject, String optionalEntityName, Object optionalIdentifier, IEntityPersister persister) at NHibernate.Loader.Entity.AbstractEntityLoader.Load(ISessionImplementor session, Object id, Object optionalObject, Object optionalId) at NHibernate.Loader.Entity.AbstractEntityLoader.Load(Object id, Object optionalObject, ISessionImplementor session) at NHibernate.Persister.Entity.AbstractEntityPersister.Load(Object id, Object optionalObject, LockMode lockMode, ISessionImplementor session) at NHibernate.Event.Default.DefaultLoadEventListener.LoadFromDatasource(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options) at NHibernate.Event.Default.DefaultLoadEventListener.DoLoad(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options) at NHibernate.Event.Default.DefaultLoadEventListener.Load(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options) at NHibernate.Event.Default.DefaultLoadEventListener.ProxyOrLoad(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options) at NHibernate.Event.Default.DefaultLoadEventListener.OnLoad(LoadEvent event, LoadType loadType) at NHibernate.Impl.SessionImpl.FireLoad(LoadEvent event, LoadType loadType) at NHibernate.Impl.SessionImpl.Get(String entityName, Object id) at NHibernate.Impl.SessionImpl.Get[T](Object id) at Codera.Data.NHibernate.NHRepository1.Get(Object id) at Castle.Proxies.Invocations.NHRepository1_Get_10.InvokeMethodOnTarget() at Castle.DynamicProxy.AbstractInvocation.Proceed() at ISOQuest.Data.NHibernate.Interceptors.MethodInterceptor.Intercept(IInvocation invocation) in C:\Projects\ISOQuestGen6\ISOQuest.Data.NHibernate\Interceptors\MethodInterceptor.cs:line 49 at Castle.DynamicProxy.AbstractInvocation.Proceed()at Castle.Proxies.DepartmentRepositoryProxy.Get(Object id) at ISOQuest.Business.Services.DepartmentService.GetDepartmentAdministrators(Guid DepartmentId, Int32 type) in C:\Projects\ISOQuestGen6\Modules\ISOQuest\ISOQuest.Business\Services\Department\DepartmentService.cs:line 838 at ISOQuest.Web.Controllers.Api.DepartmentsController.LoadDepartmentAdministrators(Guid DepartmentId, Int32 type) in C:\Projects\ISOQuestGen6\Modules\ISOQuest\ISOQuest.Web\Controllers\Api\DepartmentsController.cs:line 454 at lambda_method(闭包、控制器库、对象[] ) at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 个参数) at System.Web.Mvc.Async.AsyncControllerActionInvoker.b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult2.CallEndDelegate(IAsyncResult asyncResult) at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d() at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) at System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) at System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) at System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) at System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completeSyncally)

尝试完所有内容后,我又回到了nHibernate 5.X更改日志,最后来到了这里: https://nhibernate.info/doc/nhibernate-reference/transactions.html,并在更新日志的最后找到了这个小注释:

从 NHibernate v5.0 开始,FlushMode.Commit 要求配置设置 transaction.use_connection_on_system_prepare 为 true,才能从事务范围提交刷新。否则,您有责任在完成作用域之前刷新会话。使用 transaction.use_connection_on_system_prepare 可能会导致分发不需要的事务升级:它需要使用专用连接进行刷新,并且它会延迟会话处置(如果在作用域内完成)到作用域处置。如果要避免这种情况,请将此设置设置为 false 并手动刷新会话。

对于新应用程序,建议将transaction.use_connection_on_system_prepare设置为 false,并在范围完成之前显式刷新会话。对于旧应用程序,请考虑检查会话的刷新方式,如果可能,也将其切换为 false。

基本上,我们在迁移到nHibernate 5时更改的一个设置是FlushMode从"自动"到"提交",但不知何故错过了这个标志(transaction.use_connection_on_system_prepare= false)。

希望这能帮助其他尝试升级遗留系统的人!

相关内容

最新更新