丢失物理连接

时间:2014-12-31 13:48:33

标签: vb.net

我在日常文件中看到此错误:

A transport-level error has occurred when receiving results from the server. (provider: Session Provider, error: 19 - Physical connection is not usable)

相关代码每天执行5000次删除。每次删除有三个或四个数据库连接。

最初我认为代码存在问题(ADO.NET),即连接池中的连接由于未处理的资源而被耗尽,例如连接,命令和数据引导器。我遇到过以下代码,这是由其他人编写的:

Public Overloads Shared Function ExecuteReader(ByVal connectionString As String, _
                                                       ByVal commandType As CommandType, _
                                                       ByVal commandText As String, _
                                                       ByVal ParamArray commandParameters() As DbParameter) As DbDataReader
            If (connectionString Is Nothing OrElse connectionString.Length = 0) Then Throw New ArgumentNullException("connectionString")

            ' Create & open a SqlConnection
            Dim connection As SqlConnection = Nothing
            Try
                connection = New SqlConnection(connectionString)
                connection.Open()
                ' Call the private overload that takes an internally owned connection in place of the connection string
                Return ExecuteReader(connection, CType(Nothing, SqlTransaction), commandType, commandText, commandParameters, dbConnectionOwnership.Internal)
            Catch
                ' If we fail to return the SqlDatReader, we need to close the connection ourselves
                If Not connection Is Nothing Then connection.Dispose()
                Throw
            End Try
        End Function

Private Overloads Shared Function ExecuteReader(ByVal connection As DbConnection, _
                                                            ByVal transaction As DbTransaction, _
                                                            ByVal commandType As CommandType, _
                                                            ByVal commandText As String, _
                                                            ByVal commandParameters() As DbParameter, _
                                                            ByVal connectionOwnership As dbConnectionOwnership, Optional ByVal intTimeOut As Integer = 30) As DbDataReader

            If (connection Is Nothing) Then Throw New ArgumentNullException("connection")

            Dim mustCloseConnection As Boolean = False
            Dim cmd As DbCommand
            ' Create a command and prepare it for execution
            If TypeOf (connection) Is SqlConnection Then
                cmd = New SqlCommand
            ElseIf TypeOf (connection) Is OracleConnection Then
                cmd = New OracleCommand
            Else
                cmd = Nothing
            End If
            cmd.CommandTimeout = intTimeOut
            Try
                ' Create a reader
                Dim dataReader As DbDataReader

                PrepareCommand(cmd, connection, transaction, commandType, commandText, commandParameters, mustCloseConnection)
                ' Call ExecuteReader with the appropriate CommandBehavior
                If connectionOwnership = dbConnectionOwnership.External Then
                    dataReader = cmd.ExecuteReader()
                Else
                    dataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
                End If

                ' Detach the SqlParameters from the command object, so they can be used again
                Dim canClear As Boolean = True
                Dim commandParameter As DbParameter
                For Each commandParameter In cmd.Parameters
                    If commandParameter.Direction <> ParameterDirection.Input Then
                        canClear = False
                    End If
                Next

                If (canClear) Then cmd.Parameters.Clear()

                Return dataReader
            Catch
                If (mustCloseConnection) Then connection.Close()
                Throw
            End Try
        End Function

Private Shared Sub PrepareCommand(ByVal command As DbCommand, _
                                          ByVal connection As DbConnection, _
                                          ByVal transaction As DbTransaction, _
                                          ByVal commandType As CommandType, _
                                          ByVal commandText As String, _
                                          ByVal commandParameters() As DbParameter, ByRef mustCloseConnection As Boolean)

        If (command Is Nothing) Then Throw New ArgumentNullException("command")
        If (commandText Is Nothing OrElse commandText.Length = 0) Then Throw New ArgumentNullException("commandText")

        ' If the provided connection is not open, we will open it
        If connection.State <> ConnectionState.Open Then
            connection.Open()
            mustCloseConnection = True
        Else
            mustCloseConnection = False
        End If

        ' Associate the connection with the command
        command.Connection = connection

        ' Set the command text (stored procedure name or SQL statement)
        command.CommandText = commandText

        ' If we were provided a transaction, assign it.
        If Not (transaction Is Nothing) Then
            If transaction.Connection Is Nothing Then Throw New ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction")
            command.Transaction = transaction
        End If

        ' Set the command type
        command.CommandType = commandType

        ' Attach the command parameters if they are provided
        If Not (commandParameters Is Nothing) Then
            AttachParameters(command, commandParameters)
        End If
        Return
    End Sub ' PrepareCommand

我相信这是Code Blocks的一部分,它是在2008年从Microsoft网站下载的。我相信这段代码不会破坏连接对象(除非抛出异常)。我想这可能是原因?

1 个答案:

答案 0 :(得分:0)

您应该将您的连接放在USING块中,以便它被关闭并处置属性,无论是否有错误。例如:

Using connection As New SqlConnection(connectionString)
        Try
            connection.Open()
            ' Call the private overload that takes an internally owned connection in place of the connection string
            Return ExecuteReader(connection, CType(Nothing, SqlTransaction), commandType, commandText, commandParameters, dbConnectionOwnership.Internal)
        Catch
            ' If we fail to return the SqlDatReader, we need to close the connection ourselves
            Throw
        End Try
End Using

如果连接处于打开状态并且网络中出现一些故障,我通常会看到此错误,然后您尝试使用该连接。不是说这是你的问题,但USING声明肯定会改进你的代码。