H
hkd
I have written a multi threaded Windows service in c#, .net 2.0. The
application sends data to a database using stored procedures. The
application works fine on a LAN, but I cannot stabilize it over our
WAN links. The WAN connectivity is fairly high speed (DS3), but has a
high latency (average 250 milliseconds).
The problem I am experiencing appears to be related to the
underlying .net TdsParser code. After the applcation runs for 30-60
minutes, it begins to throw SqlClient exceptions. After restarting the
application, the problem reoccurs within seconds. If I leave it alone
overnight, I can repeat this cycle. It would seem that the problem
sticks around waiting for internal garbage collection (?).
I have tried changing to a non pooled connection with no luck. The
code doing the connection is not in a static method, so no lock or
Monitor code uis involved. I have seen a fair amount of complaints
regarding such occurances, but no resolutions.
Can anybody shed some light on this? Thanks for the time.
******************************
***********details **********
******************************
Perfmon confirms that all is well for awhile, then goes haywire. What
I see there is:
Start, normal operation:
NumberOfInactiveConnectionPools: 9-10
NumberOfPooledConnections: 20-22
after "the hammer" falls:
NumberOfInactiveConnectionPools: 0, rises over a few minutes to 90 or
so, drops down to 0 and repeats
NumberOfPooledConnections: 0-2 (as they are failing)
HardConnectsPerSecond: 4-6
HardDisconnectsPerSecond: 4-6
Exceptions/sec.:4-6
**********************************
A stack trace:
The Stored Proceedure MyStoredProc failed, it returned
System.Data.SqlClient.SqlException: A transport-level error has
occurred when receiving results from the server. (provider: TCP
Provider, error: 0 - An existing connection was forcibly closed by the
remote host.)
at System.Data.SqlClient.SqlConnection.OnError(SqlException
exception, Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException
exception, Boolean breakConnection)
at
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject
stateObj)
at
System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject
stateObj, UInt32 error)
at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult
asyncResult, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParserStateObject.ReadPacket(Int32
bytesExpected)
at System.Data.SqlClient.TdsParserStateObject.ReadBuffer()
at System.Data.SqlClient.TdsParserStateObject.ReadByte()
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior,
SqlCommand cmdHandler, SqlDataReader dataStream,
BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject
stateObj)
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)
at
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String
method, DbAsyncResult result)
at
System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult
result, String methodName, Boolean sendToPipe)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at Resource.foo()
**********************************
The code:
private void foo()
{
//"Database=MyDb;Server=MyDbServer;Max Pool
Size=500;Integrated Security=SSPI;
// Connection Timeout=1800;Network Library=dbmssocn;";
SqlConnection oConn = new
SqlConnection(Globals.DbConnectionString);
SqlCommand oCmd = new SqlCommand();
try
{
oConn.Open();
oCmd = new SqlCommand("MyStoredProc", oConn);
oCmd.CommandType = CommandType.StoredProcedure;
oCmd.CommandTimeout = Globals.CommandTimeout; // 3600,
server set to 0 (no timeout)
oCmd.Parameters.Add(new SqlParameter("@GUID", _Guid));
oCmd.Parameters.Add(new SqlParameter("@CreatedOn",
_dtCreated));
oCmd.Parameters.Add(new SqlParameter("@ModifiedOn",
_dtLastModified));
oCmd.Parameters.Add(new
SqlParameter("@LastAccessedOn", _dtLastAccessed));
oCmd.Parameters.Add(new SqlParameter("@Size", _size));
oCmd.Parameters.Add("@RETURN",
SqlDbType.Int).Direction = ParameterDirection.Output;
try
{
int iRc = oCmd.ExecuteNonQuery();
if (oCmd.Parameters["@RETURN"].Value == null)
throw new
CustomException(EventId.WARNING_DATASET_GENERIC, "The Stored
Proceedure " +
oCmd.CommandText + " did not return a
result code. An insertion may have failed.");
iRc = (int)oCmd.Parameters["@RETURN"].Value;
switch (iRc)
{
case 0:
break;
default:
throw new
CustomException(EventId.WARNING_DATASET_GENERIC, "The Stored
Proceedure " +
oCmd.CommandText + " failed, it
returned " + iRc.ToString());
}
}
catch (System.Data.SqlClient.SqlException e)
{
SqlConnection.ClearPool(oConn);
throw new
CustomException(EventId.WARNING_DATASET_GENERIC, "The Stored
Proceedure " +
oCmd.CommandText + " failed, it returned " +
e.ToString());
}
}
catch (NullReferenceException e)
{
throw new CustomException(EventId.WARNING_GENERIC, "An
unexpcected error was encountered while adding "
+ "a resource to the database. The system reports:"
+ e.ToString());
}
finally
{
if (oCmd != null)
oCmd.Dispose();
if (oConn != null)
{
if (oConn.State != ConnectionState.Closed &&
oConn.State != ConnectionState.Broken)
oConn.Close();
oConn.Dispose();
}
}
}
application sends data to a database using stored procedures. The
application works fine on a LAN, but I cannot stabilize it over our
WAN links. The WAN connectivity is fairly high speed (DS3), but has a
high latency (average 250 milliseconds).
The problem I am experiencing appears to be related to the
underlying .net TdsParser code. After the applcation runs for 30-60
minutes, it begins to throw SqlClient exceptions. After restarting the
application, the problem reoccurs within seconds. If I leave it alone
overnight, I can repeat this cycle. It would seem that the problem
sticks around waiting for internal garbage collection (?).
I have tried changing to a non pooled connection with no luck. The
code doing the connection is not in a static method, so no lock or
Monitor code uis involved. I have seen a fair amount of complaints
regarding such occurances, but no resolutions.
Can anybody shed some light on this? Thanks for the time.
******************************
***********details **********
******************************
Perfmon confirms that all is well for awhile, then goes haywire. What
I see there is:
Start, normal operation:
NumberOfInactiveConnectionPools: 9-10
NumberOfPooledConnections: 20-22
after "the hammer" falls:
NumberOfInactiveConnectionPools: 0, rises over a few minutes to 90 or
so, drops down to 0 and repeats
NumberOfPooledConnections: 0-2 (as they are failing)
HardConnectsPerSecond: 4-6
HardDisconnectsPerSecond: 4-6
Exceptions/sec.:4-6
**********************************
A stack trace:
The Stored Proceedure MyStoredProc failed, it returned
System.Data.SqlClient.SqlException: A transport-level error has
occurred when receiving results from the server. (provider: TCP
Provider, error: 0 - An existing connection was forcibly closed by the
remote host.)
at System.Data.SqlClient.SqlConnection.OnError(SqlException
exception, Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException
exception, Boolean breakConnection)
at
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject
stateObj)
at
System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject
stateObj, UInt32 error)
at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult
asyncResult, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParserStateObject.ReadPacket(Int32
bytesExpected)
at System.Data.SqlClient.TdsParserStateObject.ReadBuffer()
at System.Data.SqlClient.TdsParserStateObject.ReadByte()
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior,
SqlCommand cmdHandler, SqlDataReader dataStream,
BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject
stateObj)
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)
at
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String
method, DbAsyncResult result)
at
System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult
result, String methodName, Boolean sendToPipe)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at Resource.foo()
**********************************
The code:
private void foo()
{
//"Database=MyDb;Server=MyDbServer;Max Pool
Size=500;Integrated Security=SSPI;
// Connection Timeout=1800;Network Library=dbmssocn;";
SqlConnection oConn = new
SqlConnection(Globals.DbConnectionString);
SqlCommand oCmd = new SqlCommand();
try
{
oConn.Open();
oCmd = new SqlCommand("MyStoredProc", oConn);
oCmd.CommandType = CommandType.StoredProcedure;
oCmd.CommandTimeout = Globals.CommandTimeout; // 3600,
server set to 0 (no timeout)
oCmd.Parameters.Add(new SqlParameter("@GUID", _Guid));
oCmd.Parameters.Add(new SqlParameter("@CreatedOn",
_dtCreated));
oCmd.Parameters.Add(new SqlParameter("@ModifiedOn",
_dtLastModified));
oCmd.Parameters.Add(new
SqlParameter("@LastAccessedOn", _dtLastAccessed));
oCmd.Parameters.Add(new SqlParameter("@Size", _size));
oCmd.Parameters.Add("@RETURN",
SqlDbType.Int).Direction = ParameterDirection.Output;
try
{
int iRc = oCmd.ExecuteNonQuery();
if (oCmd.Parameters["@RETURN"].Value == null)
throw new
CustomException(EventId.WARNING_DATASET_GENERIC, "The Stored
Proceedure " +
oCmd.CommandText + " did not return a
result code. An insertion may have failed.");
iRc = (int)oCmd.Parameters["@RETURN"].Value;
switch (iRc)
{
case 0:
break;
default:
throw new
CustomException(EventId.WARNING_DATASET_GENERIC, "The Stored
Proceedure " +
oCmd.CommandText + " failed, it
returned " + iRc.ToString());
}
}
catch (System.Data.SqlClient.SqlException e)
{
SqlConnection.ClearPool(oConn);
throw new
CustomException(EventId.WARNING_DATASET_GENERIC, "The Stored
Proceedure " +
oCmd.CommandText + " failed, it returned " +
e.ToString());
}
}
catch (NullReferenceException e)
{
throw new CustomException(EventId.WARNING_GENERIC, "An
unexpcected error was encountered while adding "
+ "a resource to the database. The system reports:"
+ e.ToString());
}
finally
{
if (oCmd != null)
oCmd.Dispose();
if (oConn != null)
{
if (oConn.State != ConnectionState.Closed &&
oConn.State != ConnectionState.Broken)
oConn.Close();
oConn.Dispose();
}
}
}