PC Review


Reply
Thread Tools Rate Thread

Connection Pooling LEAK?

 
 
Owen Mortensen
Guest
Posts: n/a
 
      9th Feb 2005
Why is this not working (i.e., it leaks a connection EVERY TIME)?

<code>
Imports System.Configuration
Imports System.Data.SqlClient
Imports System.Web

Public Class dBUtils
Implements IDisposable

'***************************
'* PRIVATE Local variables *
'***************************
Private strConnectionString As String
Private objConn As SqlClient.SqlConnection
Private nCommandTimeout As Integer
Private objTrans As SqlTransaction

'***********************************************************************************
'* New()
Private Sub New()
'The constructor with no parameters is PRIVATE so no that the object
cannot be
'created without passing in the database identifier.
End Sub

Public Sub New(ByVal strDatabaseIdentifier As String)
strConnectionString =
ConfigurationSettings.AppSettings(strDatabaseIdentifier)
nCommandTimeout =
CInt(ConfigurationSettings.AppSettings("CommandTimeout"))
objConn = New SqlClient.SqlConnection(strConnectionString)
objConn.Open()
End Sub

'***********************************************************************************
'* GetDataReader( strSQL, booIsStoredProc )
*
Public Function GetDataReader(ByVal strSQL As String, ByVal
booIsStoredProc As Boolean) As SqlDataReader
'execute SQL string and return a dataReader object
Dim objCommand As New SqlCommand(strSQL, objConn)
Dim objDataReader As SqlDataReader

If booIsStoredProc Then
objCommand.CommandType = CommandType.StoredProcedure
Else
objCommand.CommandType = CommandType.Text
End If
objCommand.CommandTimeout = nCommandTimeout
Dim objResult As SqlDataReader = objCommand.ExecuteReader()
objCommand.Dispose()

Return objResult

End Function

'***********************************************************************************
'* BeginTrans
Public Sub BeginTrans()
objTrans = objConn.BeginTransaction()
End Sub

'***********************************************************************************
'* CommitTrans
Public Sub CommitTrans()
Try
objTrans.Commit()
Catch e As Exception
'Do nothing here
End Try
End Sub

'***********************************************************************************
'* RollbackTrans
Public Sub RollbackTrans()
Try
objTrans.Rollback()
Catch e As Exception
'do nothing here
End Try
End Sub

'***********************************************************************************
'* Dispose()
Public Sub Dispose() Implements System.IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub

Private Sub Dispose(ByVal booDisposing As Boolean)
If booDisposing Then
Try
HttpContext.Current.Response.Write("Disposing<br>")
objConn.Close()
objConn = Nothing
Catch ex As Exception
'Do nothing
End Try

End If
End Sub

'***********************************************************************************
'* Finalize()
Protected Overrides Sub Finalize()
Me.Dispose(False)
MyBase.Finalize()
End Sub
End Class

Then, the calling routine does this:
Dim objDb as dBUtils
objDb = New dBUtils("SQL_db1")
Dim objRS As SqlDataReader
objRS = objDb.GetDataReader("SELECT * FROM tbl1", false)
do while objRS.Read()
....
loop
objRS.Close()
objDb.Dispose()
</code>

Now, the problem is, EVERY SINGLE TIME this is executed, I get another
connection added to the connection pool. Eventually, I run out of pooled
connections and the open times out.

Any ideas?

TIA,
Owen


 
Reply With Quote
 
 
 
 
NuTcAsE
Guest
Posts: n/a
 
      9th Feb 2005
Im asuming this is an ASP.Net application. Asuming the code is executed
whenever a user clicks a button, the following steps happen:

1. A new instance of DbUtils is created
2. Execute reader is called,
3. Processing is done, and DbUtils.Dispose is called
4. In DbUtils the connection is closed and set to nothing * (Dispose is
never called on the connection)

Now if you look at the sequence above, if you have 300 ppl hitting the
same page at the same time, you may at any given point in time going to
have 300 connections open... this may not seem bad as this normally
happens in most web apps. But the Dispose function of your dbUtils
never disposes of those connections. So youve still got unmanaged
connections that hvnt been released and so a connection to the pool is
always added. This situtation will remain until the GC kicks in and
manually finalizes those connections.

In the Dispose function of the dbUtils, add objConn.Dispose also. This
should then free up the connection pool.

Hope this helps.

NuTcAsE

 
Reply With Quote
 
Owen Mortensen
Guest
Posts: n/a
 
      9th Feb 2005
Thanks. I'll do that. I did find the leak: it was outside the dbUtils
object in another part of the site. Single-step debugging really helped that
one.

Owen

"NuTcAsE" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Im asuming this is an ASP.Net application. Asuming the code is executed
> whenever a user clicks a button, the following steps happen:
>
> 1. A new instance of DbUtils is created
> 2. Execute reader is called,
> 3. Processing is done, and DbUtils.Dispose is called
> 4. In DbUtils the connection is closed and set to nothing * (Dispose is
> never called on the connection)
>
> Now if you look at the sequence above, if you have 300 ppl hitting the
> same page at the same time, you may at any given point in time going to
> have 300 connections open... this may not seem bad as this normally
> happens in most web apps. But the Dispose function of your dbUtils
> never disposes of those connections. So youve still got unmanaged
> connections that hvnt been released and so a connection to the pool is
> always added. This situtation will remain until the GC kicks in and
> manually finalizes those connections.
>
> In the Dispose function of the dbUtils, add objConn.Dispose also. This
> should then free up the connection pool.
>
> Hope this helps.
>
> NuTcAsE
>



 
Reply With Quote
 
David Browne
Guest
Posts: n/a
 
      9th Feb 2005

"NuTcAsE" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Im asuming this is an ASP.Net application. Asuming the code is executed
> whenever a user clicks a button, the following steps happen:
>
> 1. A new instance of DbUtils is created
> 2. Execute reader is called,
> 3. Processing is done, and DbUtils.Dispose is called
> 4. In DbUtils the connection is closed and set to nothing * (Dispose is
> never called on the connection)


Which is fine since SQLConnection.Close will return the connection to the
pool.

>
> Now if you look at the sequence above, if you have 300 ppl hitting the
> same page at the same time, you may at any given point in time going to
> have 300 connections open... this may not seem bad as this normally
> happens in most web apps.


There will be fewer than 300 because there are typically not 300 threads in
the ASP.NET worker thread pool.

>But the Dispose function of your dbUtils
> never disposes of those connections.


Wrong.

>So youve still got unmanaged
> connections that hvnt been released and so a connection to the pool is
> always added. This situtation will remain until the GC kicks in and
> manually finalizes those connections.


Again, Nope. SqlConnection.Close is fine. SqlConnection.Dispose would be
fine too, but there's nothing really wrong with just using .Close.

The only flaw in the OP's code is


Private Sub Dispose(ByVal booDisposing As Boolean)
If booDisposing Then
Try
HttpContext.Current.Response.Write("Disposing<br>")
objConn.Close()
objConn = Nothing
Catch ex As Exception
'Do nothing
End Try

End If
End Sub

Should be

Private Sub Dispose(ByVal booDisposing As Boolean)
If booDisposing Then
objConn.Close()
objConn = Nothing
Try
HttpContext.Current.Response.Write("Disposing<br>")
Catch ex As Exception
'Do nothing
End Try

End If
End Sub

So an exception on
HttpContext.Current.Response.Write("Disposing<br>")
won't cause a connection leak.

David




David


 
Reply With Quote
 
William Ryan eMVP
Guest
Posts: n/a
 
      10th Feb 2005
Owen: It looks like David has answered the crusx of your problem., but if
I may chime in - There are probably more elegant ways to accomplish what you
want - particularly in the context of a Try/Catch/Finally block and using
the CloseConnection enumeration for the CommandBehavior.

Also, as a matter of pragmatism - catching System.Exception and doing
nothing with it is bad++ At each point you close then trap the exception -
why not move it to a finally block - if a StackOVerflow happened - you don't
know that the code would execute. Granted this isn't going to be a very
common scenario - but it doesn't cost anything to do and serves as a much
more solid insurance policyh.

--
W.G. Ryan MVP Windows - Embedded

Have an opinion on the effectiveness of Microsoft Embedded newsgroups?
Let Microsoft know!
https://www.windowsembeddedeval.com/...ity/newsgroups
"Owen Mortensen" <(E-Mail Removed)> wrote in message
news:%(E-Mail Removed)...
> Why is this not working (i.e., it leaks a connection EVERY TIME)?
>
> <code>
> Imports System.Configuration
> Imports System.Data.SqlClient
> Imports System.Web
>
> Public Class dBUtils
> Implements IDisposable
>
> '***************************
> '* PRIVATE Local variables *
> '***************************
> Private strConnectionString As String
> Private objConn As SqlClient.SqlConnection
> Private nCommandTimeout As Integer
> Private objTrans As SqlTransaction
>
>

'***************************************************************************
********
> '* New()
> Private Sub New()
> 'The constructor with no parameters is PRIVATE so no that the object
> cannot be
> 'created without passing in the database identifier.
> End Sub
>
> Public Sub New(ByVal strDatabaseIdentifier As String)
> strConnectionString =
> ConfigurationSettings.AppSettings(strDatabaseIdentifier)
> nCommandTimeout =
> CInt(ConfigurationSettings.AppSettings("CommandTimeout"))
> objConn = New SqlClient.SqlConnection(strConnectionString)
> objConn.Open()
> End Sub
>
>

'***************************************************************************
********
> '* GetDataReader( strSQL, booIsStoredProc )
> *
> Public Function GetDataReader(ByVal strSQL As String, ByVal
> booIsStoredProc As Boolean) As SqlDataReader
> 'execute SQL string and return a dataReader object
> Dim objCommand As New SqlCommand(strSQL, objConn)
> Dim objDataReader As SqlDataReader
>
> If booIsStoredProc Then
> objCommand.CommandType = CommandType.StoredProcedure
> Else
> objCommand.CommandType = CommandType.Text
> End If
> objCommand.CommandTimeout = nCommandTimeout
> Dim objResult As SqlDataReader = objCommand.ExecuteReader()
> objCommand.Dispose()
>
> Return objResult
>
> End Function
>
>

'***************************************************************************
********
> '* BeginTrans
> Public Sub BeginTrans()
> objTrans = objConn.BeginTransaction()
> End Sub
>
>

'***************************************************************************
********
> '* CommitTrans
> Public Sub CommitTrans()
> Try
> objTrans.Commit()
> Catch e As Exception
> 'Do nothing here
> End Try
> End Sub
>
>

'***************************************************************************
********
> '* RollbackTrans
> Public Sub RollbackTrans()
> Try
> objTrans.Rollback()
> Catch e As Exception
> 'do nothing here
> End Try
> End Sub
>
>

'***************************************************************************
********
> '* Dispose()
> Public Sub Dispose() Implements System.IDisposable.Dispose
> Dispose(True)
> GC.SuppressFinalize(Me)
> End Sub
>
> Private Sub Dispose(ByVal booDisposing As Boolean)
> If booDisposing Then
> Try
> HttpContext.Current.Response.Write("Disposing<br>")
> objConn.Close()
> objConn = Nothing
> Catch ex As Exception
> 'Do nothing
> End Try
>
> End If
> End Sub
>
>

'***************************************************************************
********
> '* Finalize()
> Protected Overrides Sub Finalize()
> Me.Dispose(False)
> MyBase.Finalize()
> End Sub
> End Class
>
> Then, the calling routine does this:
> Dim objDb as dBUtils
> objDb = New dBUtils("SQL_db1")
> Dim objRS As SqlDataReader
> objRS = objDb.GetDataReader("SELECT * FROM tbl1", false)
> do while objRS.Read()
> ....
> loop
> objRS.Close()
> objDb.Dispose()
> </code>
>
> Now, the problem is, EVERY SINGLE TIME this is executed, I get another
> connection added to the connection pool. Eventually, I run out of pooled
> connections and the open times out.
>
> Any ideas?
>
> TIA,
> Owen
>
>



 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How can I force connection pooling to keep at least one connection alive ? TheSteph Microsoft C# .NET 6 22nd Nov 2007 03:25 PM
Connection pooling parameters not working for Oracle connection yoram.ayalon@structuredweb.com Microsoft ADO .NET 1 29th Sep 2006 09:36 PM
Connection pooling: Ok, I give up. Where's my leak??????? X_Factor Microsoft ADO .NET 5 2nd Sep 2004 05:03 PM
connection in connection pool with pooling=false Jason Collins Microsoft ADO .NET 10 22nd Jun 2004 01:21 PM
How do I turn off connection pooling in a connection string corbett Microsoft Dot NET 1 6th Jan 2004 11:36 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 05:17 PM.