Bug in SqlParameter collection
I hate to be so vague while trying to characterize something, but I can
only describe what we have seen so far. We have a typical n-tier system
that is comprised of the usual ASP.NET, BF, Biz, Data Access and DB
layers. The Biz layer code uses serviced .NET components. The Data Access
Layer components use Microsoft's SqlHelper helper class to execute various
operations on the DB using stored procedures.
We also have a managed Windows service that occasionally wakes up and
performs certain opertations using the Biz Layer components. The Windows
service code path is traversed thousands of times w/o any problems, but
occasionally, we see an error that looks something like this:
<paste>
Exception Type: System.ArgumentException
Message: The SqlParameter with ParameterName '@XXXXX' is already contained
by another SqlParameterCollection.
ParamName: NULL
TargetSite: Void Validate(Int32, System.Data.SqlClient.SqlParameter)
HelpLink: NULL
Source: System.Data
</paste>
We have pored over the code several times and have concluded that the most
likely explanation is a bug in the SqlParameter's caching of SP
parameters. We are certain that reentrancy is not an issue in this case.
Has anyone else run into this problem before? Note that there's no
reliable known method of reproducing this problem. It seemingly happens at
random and once we run into this situation, the only recourse seems to be
to restart the service.
Atul
Quick thought. Are you calling the public static SqlParameter[]
GetSpParameterSet method and then using this array of parameters in
multiple calls into the various Execute methods. One hole I see is that
the Execute methods that take the SqlParameter[] as a parameter, it does
do a cmd.Parameters.Clear() but this is not part of a try/finally block.
So it's possible that a prior cmd.Execute method throws an exception and
the parameters are not cleared. But if you are always using the methods
that derive an array of parameters from the cache by cloning them,
you "shouldn't" have a problem.
-Chad
Well, we allocate a new array of SqlParmeters every single time and I
don't think that the function that's throwing the exception gets any
simpler than this:
public static void Foo(int blah)
{
SqlParameter[] arrParameters = new SqlParameter[1];
arrParameters[0] = new SqlParameter( "@XXXXX",
SqlDbType.Int );
arrParameters[0].Value = blah;
SqlHelper.ExecuteNonQuery("connection string",
CommandType.StoredProcedure, "SP Name", arrParameters );
}
浙公网安备 33010602011771号