从 linux 的 dot net core 连接到远程 sql server 有时会失败,然后开始随机工作

Posted

技术标签:

【中文标题】从 linux 的 dot net core 连接到远程 sql server 有时会失败,然后开始随机工作【英文标题】:Connecting to remote sql server from dot net core from linux sometimes fails, then starts working randomly 【发布时间】:2020-06-13 03:26:53 【问题描述】:

我有一个C# dotnet core 3.1 Asp.net MVC 应用程序在Ubuntu 18.04 上运行。它使用Entity Framework 连接到在Windows Server 2016 上运行的远程Sql Server。大多数时候,连接和查询工作正常。但是,偶尔,特别是如果连接应用程序没有收到任何查询数据库的请求,我会收到这个超时错误:

fail: Microsoft.EntityFrameworkCore.Query[10100]
      An exception occurred in the database while iterating the results of a query for context type 'OptionsAPI.Services.OptionsDbContext'.
      System.Data.SqlClient.SqlException (0x80131904): Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
       ---> System.ComponentModel.Win32Exception (258): Unknown error 258
         at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
         at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
         at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
         at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
         at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
         at System.Data.SqlClient.SqlDataReader.get_MetaData()
         at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
         at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
         at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite, String method)
         at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
         at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior)
         at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
         at System.Data.Common.DbCommand.ExecuteReader()
         at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary`2 parameterValues)
         at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
         at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
         at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()
      ClientConnectionId:a5e255ac-8539-4e14-96fe-71a7d565cc88
      Error Number:-2,State:0,Class:11
System.Data.SqlClient.SqlException (0x80131904): Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
 ---> System.ComponentModel.Win32Exception (258): Unknown error 258
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
   at System.Data.SqlClient.SqlDataReader.get_MetaData()
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite, String method)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.ExecuteReader()
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()
ClientConnectionId:a5e255ac-8539-4e14-96fe-71a7d565cc88
Error Number:-2,State:0,Class:11

我不确定为什么会这样。我意识到这有点模糊,但我已经在互联网上搜索过类似的问题,但我不知道下一步该怎么做,但问了一个模糊的问题。

【问题讨论】:

【参考方案1】:

您是否注意到错误消息是如何显示“超时或断开连接”的?您可能正在为远程 mssql 分配一个长时间运行的操作,而您的客户端设置为不等待那么长时间。有一种方法可以在客户端设置更长或无限期的连接超时。您可以通过连接字符串或通过 SqlConnection/SqlCommand 实例上的 Timeout 属性来执行此操作。如果超时确实是问题,您应该考虑研究如何优化该数据库工作,导致保持连接打开 10 分钟以上(我认为默认为 10 分钟),因为任何听起来都不好。

另外调查你没有以某种方式引用一些与你的 sqlclient 相关的 .Net Framework 包(而不是 dotnetcore) - 我发现在那个错误的堆栈跟踪中提到 Win32 很奇怪,这似乎都与发生在客户端的过程。也许有些东西不完全兼容。查看是否有 EF 核心包的更新。我知道上次我使用它时他们有错误,所以这不会让我感到惊讶。

或者,检查您对 OptionsDbContext 实例的使用情况,并确保在完成数据库工作后关闭/处置/销毁它。 EF 的 DbContext 旨在仅用于单个工作单元,不应保留在其他线程或未来进程/请求中使用。如果您使用的是 DI,请确保该实例和使用它的任何其他对象未注册为单例。您的错误表明它可能是由于忘记(未关闭)连接而导致的,该连接最终会断开(默认情况下,客户端会在 10 分钟后断开),从而引发该异常作为副作用。

【讨论】:

超时是SqlCommand的属性,不是SqlConnection的。 SqlConnection 仅控制连接超时。见docs.microsoft.com/en-us/dotnet/api/… 感谢您的澄清。

以上是关于从 linux 的 dot net core 连接到远程 sql server 有时会失败,然后开始随机工作的主要内容,如果未能解决你的问题,请参考以下文章

Dot Net Core dll 作为带有事件的 COM dll

如何使用jquery从dot net core mvc中的表中的下拉列表中显示选定的值

Dot.Net Core 中 Azure blob 容器中的软删除 blob 文件

使用自包含框架时,dot net core 3.1 的设置 CI 构建配置失败

C# dot net core 单实例应用程序将参数传递给第一个实例

从 Visual Studio Code、Dot Net 连接 MySQL Db