timeout exception

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I have a vb.NET solution with a Windows Application project that contains my user interface and a Class Library project that contains (among other things) a class I call DataAccessComponent. This class inherits from System.ComponentModel.Component and contains a single SQLConnection object and a bunch of SQLDataAdapter object which reference it. It also exposes 2 methods per SQLDataAdapter object that all look more or less the same. For example

Public Function GetOrganizations(
Optional ByVal anOrganizationID As Object = Nothing) As dsNutme
Dim organizations As New dsNutme

organizations.EnforceConstraints = Fals
If Not anOrganizationID Is Nothing The
SQLDAtblOrganization.SelectCommand.Parameters("@OrganizationID").Value = CType(anOrganizationID, Long
Els
SQLDAtblOrganization.SelectCommand.Parameters("@OrganizationID").Value = System.DBNull.Valu
End I
SQLDAtblOrganization.Fill(organizations
Return organization
End Functio

Public Function UpdateOrganizations(ByVal organizationChanges
As dsNutmeg) As dsNutme
If Not (organizationChanges Is Nothing) The
SQLDAtblOrganization.Update(organizationChanges
Return organizationChange
Els
Return Nothin
End I
End Functio

My question (and I DO have one), is this: why, after several "get" calls, for exampl

Private Sub GetDat

dim mDAC as New DataAccessComponen
dim ds as new dsNutme

ds.Merge(mDAC.GetOrganizations()

' Do something with the data

End Su

, am I suddenly getting a timout exception with the advice that it might have somtehing to do with exceeding the available connections in my connection pool? I BELIEVED that I was just repeatedly using the same connection. Is this not the case? Am I not releasing connection resources properly? How SHOULD I go about doing what I'm trying to do

Thanks

Pa
 
Hi Pat,

See this text on the page I give the link beneath it.
Note that the code does not explicitly open and close the Connection. The
Fill method implicitly opens the Connection that the DataAdapter is using if
it finds that the connection is not already open. If Fill opened the
connection, it will also close the connection when Fill is finished. This
can simplify your code when dealing with a single operation such as a Fill
or an Update. However, if you are performing multiple operations that
require an open connection, you can improve the performance of your
application by explicitly calling the Open method of the Connection,
performing the operations against the data source, then calling the Close
method of the Connection. You should strive to keep connections to the data
source open for a minimal amount of time to free up the resource to be used
by other client applications.

http://msdn.microsoft.com/library/d...tml/cpconpopulatingdatasetfromdataadapter.asp

As well I looked at your update just to make you aware on it.
Public Function UpdateOrganizations(ByVal organizationChanges _
As dsNutmeg) As dsNutmeg
If Not (organizationChanges Is Nothing) Then
SQLDAtblOrganization.Update(organizationChanges)
Return organizationChanges
Else
Return Nothing
End If
End Function
In my opinion is that the same as
Public Sub UpdateOrganizations(ByVal organizationChanges _
AS dsNutMeg)
If Not (organizationChanges Is Nothing) Then
SQLDAtblOrganization.Update(organizationChanges)
End Sub

Cor
 
Thanks for the response. I changed my "Get" procedures to explicitly open and close the connection object for each fill, but no joy. I still get the following message after a number of successful (say ca. 100) connections

"An unhandled exception of type 'System.InvalidOperationException' occurred in system.data.dl

Additional information: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.

The new "Get" method format is reproduced below

Public Function GetOrganizations(
Optional ByVal anOrganizationID As Object = Nothing) As dsNutme
Dim organizations As New dsNutme

organizations.EnforceConstraints = Fals
If Not anOrganizationID Is Nothing The
SQLDAtblOrganization.SelectCommand.Parameters("@OrganizationID").Value = CType(anOrganizationID, Long
Els
SQLDAtblOrganization.SelectCommand.Parameters("@OrganizationID").Value = System.DBNull.Valu
End I
SQLConnNutmegData.Open(
SQLDAtblOrganization.Fill(organizations
SQLConnNutmegData.Close(
Return organization
End Functio

I've tried using PerformanceCounters to examine the state of my connection pool. Either I'm using them incorrectly, or that is not the problem because at no time do they show my # of pools or my # of pooled connections > 3. Incidentally, the statistics do not appear to be sensitive to whether I explicitly open and close my connection or not.

I have no idea how to proceed, but obviously the situation is unacceptable as it stands -- the user has to frequently exit and re-enter the application

BTW, the "update" format was copied right out of a Microsft walkthrough for setting-up a webservice. I didn't even really examine it until you pointed out the fact that the return value was unnecessary. I agree with you, OTOH, why did MS think that it was necessary in the walkthrough

Thanks again, and ANY advice would be MUCH appreciated

Pat
 
Hi Pat,

Angel says always to use dispose for the connection instead the close with
more than 100 connections.

There seems, with the connection, to be something extra under the hood that
the team who build that has used, however from the way he write that, I
always get the idea they are not really happy with it, and therefore they
changed it for the next version. However, you can give it a try.

Cor
 
Hmm. I tried the following scheme

dim connString as String=myConnectionString
dim conn as SQLClient.SQLConnection
dim SQLDA as SQLClient.SQLDataAdapter

if len(conn.ConnectionString)=0 then
conn=New SqlClient.SQLConnection(connString)
SQLDA.SelectCommand.Connection=conn
end if
conn.Open
SQLDA.Fill(ds)
conn.Close

The results were the same as when I simply used

SQLDA.Fill(ds)

and allowed the DataAdapter to implicitly open and close the connection.
 
Hi Pat,

I do not if it helps, however what I meant in my last message was to change
it in (see the last row inline).
dim connString as String=myConnectionString
dim conn as SQLClient.SQLConnection
dim SQLDA as SQLClient.SQLDataAdapter

if len(conn.ConnectionString)=0 then
conn=New SqlClient.SQLConnection(connString)
SQLDA.SelectCommand.Connection=conn
end if
conn.Open
SQLDA.Fill(ds)
conn.Dispose

Can you try it?

Cor
 
Woops. In fact I meant to write conn.Dispose. This seems to have no effect. I have also tried altering the Connection Timeout and the Max Pool Size in the connection string. Changing the Connection Timeout produces no discernable effect, but changing the Max Pool Size produces predictable results: increasing the Max Pool Size increases the number of connections I can make before the whole thing blows up, decreasing it does the opposite. Still, this does not actually solve the problem, it merely covers it up for a little while longer.

Also, as I said before, the whole thing is wrapped up in a Class I call DataAccessComponent. It does not seem to help if I instantiate a New DataAccessComponent each time I want to connect to the datasource.

Clearly I am grabbing connections out of the pool and not realsing them back into it, but how? Doesn't DISPOSE release them? If not, wouldn't Disposing the DataAccessComponent release them? What else can I dispose :-).

Thanks,
 
Hi Pat

Can you change it to this, I see for your other commands no reasons and I
see as well your SQL string anymore in your code. Bassicly is this all you
need.

\\\
dim conn as New SQLClient.SQLConnection(myConnectionString)
dim SQLDA as new SQLClient.SQLDataAdapter(sqlstring, conn)
conn.Open
SQLDA.Fill(ds)
conn.Dispose
///
Woops. In fact I meant to write conn.Dispose. This seems to have no
effect. I have also tried altering the Connection Timeout and the Max Pool
Size in the connection string. Changing the Connection Timeout produces no
discernable effect, but changing the Max Pool Size produces predictable
results: increasing the Max Pool Size increases the number of connections I
can make before the whole thing blows up, decreasing it does the opposite.
Still, this does not actually solve the problem, it merely covers it up for
a little while longer.
Also, as I said before, the whole thing is wrapped up in a Class I call
DataAccessComponent. It does not seem to help if I instantiate a New
DataAccessComponent each time I want to connect to the datasource.
Clearly I am grabbing connections out of the pool and not realsing them
back into it, but how? Doesn't DISPOSE release them? If not, wouldn't
Disposing the DataAccessComponent release them? What else can I dispose :-).
 
Thanks Cor.

Yes, this is much more streamlined. As it turns out, I solved my problem, and it had nothing to do with any of this. I went to the Project Properties>>Configuration Properties page and unchecked SQL Server debugging. Apparently, with SQL Server debugging enabled, the connections are not returned to the pool properly regardless of disposal. This seemed to clear up my problem, though it probably will have some other unintended side-effects :-). Thanks again for the help.

Pat
 
I think I see whay you might want to return the dataset from the update method. If you have checked the "Refresh the DataSet" option in the Advanced SQL Generation Options of the Data Adapter coniguration wizard, I believe returning the dataset will allow you to retrieve the (possibly) new PK values. I haven't verified this yet, but it makes sense.
 
Back
Top