内存泄漏/编写错误的代码或两者兼而有之 - 正确处理sqlconnection?

时间:2011-01-17 16:46:16

标签: .net design-patterns web-applications .net-1.1 sqlconnection

我正在调查一个.net 1.1 Web应用程序的问题,似乎我们有很多“内部连接致命错误”异常可能是连接对象保持打开或未正确处理。 Web服务器最终在重负载下崩溃。我检查了代码,我们实际上是在try catch finally的所有地方调用sqlconnection.close()

该项目实现以下模式。有人能告诉我它是否会导致内存泄漏?

aspx网页在Private Sub Page_Load

中进行以下调用
Dim oDictionary As New dbDictionary
tagVal = oDictionary.GetTag(41)

其中dbDictionary用于从DB获取sql表

Public Class dbDictionary
    Inherits DBInteractionBase

Public Function GetTag(ByVal tagId)

       'uses the  _connection connection object and Executes sql which sometimes throws a sql exception, but closes the connection in finally

        GetDictConnectionString()

         'new sqlconnection object for another sqlcommand
        Dim dictConnection As New SqlConnection
        dictConnection = _connection  'At this point the _connection is closed.

        'I think the dictConnection is a reference to _connection

        Dim cmdToExecute As SqlCommand = New SqlCommand

        ' // Use base class' connection object
        cmdToExecute.Connection = dictConnection

        Try
            ' // Open connection.
            dictConnection.Open()

            ' // Execute query.
            adapter.Fill(toReturn)


        Catch ex As Exception
            Throw New Exception("Error occured.", ex)
        Finally
            ' // Close connection.
            dictConnection.Close()
            cmdToExecute.Dispose()
            adapter.Dispose()
        End Try


    End Function

    Private Function GetDictConnectionString()


        ' initialize SqlCommand... Use base class _connection object
        cmdToExecute.Connection = _connection

        Try
            _connection.Open()
            adapter.Fill(toReturn)

        Catch ex As Exception
            Return "Error" ' Could this be the issue?  The original exception isn't released?
        Finally
            _connection.Close()
            cmdToExecute.Dispose()
            adapter.Dispose()
        End Try

End Class

这是它继承的DBInteractionBase

Public MustInherit Class DBInteractionBase
    Inherits System.Web.UI.Page

Protected _connection As SqlConnection

    Public Sub New()

         _connection = New SqlConnection
         _connection.ConnectionString = "some conn string"
            End Sub

    Public Overloads Sub Dispose()
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub


    Protected Overridable Overloads Sub Dispose(ByVal isDisposing As Boolean)
        ' // Check to see if Dispose has already been called.
        If Not _isDisposed Then
            If isDisposing Then
                ' // Dispose managed resources.
                _connection.Dispose()
                _connection = Nothing
            End If
        End If
        _isDisposed = True
    End Sub

现在,当代码执行时,调用网页永远不会调用Dispose。我想知道的是,如果处理代码是由GC执行的吗?我看到的另一个问题是,如果GetDictConnectionString有异常,它永远不会重新抛出原始的sql异常。这会以某种方式将sql对象留在内存中吗?请记住,这是一个.NET 1.1应用程序和(.NET 1中的GC效率不高)

此外,我想知道我可以使用perfmon在Web服务器上监视什么来指示内存泄漏。我正在计划修改此代码,并希望指出问题已得到解决。我在SqlClient中看到了一个趋势:当前#连接池 - 它每天稳定增长1000(这是与该进程关联的当前池数)。所以我想知道它是否应该随着Sessions减少而下降。我正在查看(\ ASP.NET Apps v1.1.4322( Total )\ Sessions Active)以查看服务器负载的样子。

1 个答案:

答案 0 :(得分:0)

此代码:

'new sqlconnection object for another sqlcommand
Dim dictConnection As New SqlConnection
dictConnection = _connection  'At this point the _connection is closed.

创建两个SqlConnectionAs New SqlConnection正在创建一个),第一个永远不会被处置。这当然可能是泄漏连接的来源。

您还处置了您从未创建的连接_connection(无法查看创建的位置)。假设它是以1:1创建的,这不应该是一个大问题,但如果在Try块之前发生异常,则此连接也不会被处理掉。如果没有为此代码1:1创建_connection,那么如果其他人尝试使用此代码,您最终可能会获得ObjectDisposedException