In my testing project, I have a static class called FixtureSetup which I use to setup my integration testing data for validation.
I use the same SqlCommand and SqlParameter variable (not the object itself) within that class, repeatedly, using the same variable references over and over, assigning new SqlCommand and SqlParameter objects each time. My connection itself is created once and passed into the methods performing the setup, so each setup uses it's own distinct connection reference, and while the same conn is used multiple times, it's always in a linear sequence.
In one such method, I ran into a very odd situation, where my SqlCommand variable simply appears to have gotten tired.
cmd = new SqlCommand("INSERT INTO Subscription (User_ID, Name, Active) VALUES (@User_ID, @Name, @Active)", conn);
parameter = new SqlParameter("@User_ID", TestUserID); cmd.Parameters.Add(parameter);
parameter = new SqlParameter("@Name", "TestSubscription"); cmd.Parameters.Add(parameter);
parameter = new SqlParameter("@Active", true); cmd.Parameters.Add(parameter);
cmd.ExecuteNonQuery();
cmd = new SqlCommand("SELECT Subscription_ID FROM [Subscription] WHERE Name = 'TestSubscription'", conn);
parameter = new SqlParameter("@User_ID", TestUserID);
cmd.Parameters.Add(parameter);
using (dr = cmd.ExecuteReader())
{
while (dr.Read())
{
TestSubscriptionID = dr.GetInt32(dr.GetOrdinal("Subscription_ID"));
}
}
cmd = new SqlCommand("INSERT INTO SubscriptionCompany (Subscription_ID, Company_ID) VALUES (@Subscription_ID, @Company_ID)", conn);
parameter = new SqlParameter("@Subscription_ID", TestSubscriptionID); cmd.Parameters.Add(parameter);
parameter = new SqlParameter("@Company_ID", KnownCompanyId); cmd.Parameters.Add(parameter);
cmd.ExecuteNonQuery();
In the above, at the last line shown, doing the same thing I've done quite literally in dozens of other places (insert data, read the ID column and capture it), I get the following:
SetUp : System.InvalidOperationException : ExecuteNonQuery requires an open and available Connection. The connection's current state is closed. at System.Data.SqlClient.SqlConnection.GetOpenConnection(String method)
BUT - replace cmd with new variable myCmd, and everything works swimmingly!
SqlCommand myCmd;
myCmd = new SqlCommand("INSERT INTO Subscription (User_ID, Name, Active) VALUES (@User_ID, @Name, @Active)", conn);
parameter = new SqlParameter("@User_ID", TestUserID); myCmd.Parameters.Add(parameter);
parameter = new SqlParameter("@Name", "TestSubscription"); myCmd.Parameters.Add(parameter);
parameter = new SqlParameter("@Active", true); myCmd.Parameters.Add(parameter);
myCmd.ExecuteNonQuery();
myCmd = new SqlCommand("SELECT Subscription_ID FROM [Subscription] WHERE Name = 'TestSubscription'", conn);
parameter = new SqlParameter("@User_ID", TestUserID);
myCmd.Parameters.Add(parameter);
using (dr = myCmd.ExecuteReader())
{
while (dr.Read())
{
TestSubscriptionID = dr.GetInt32(dr.GetOrdinal("Subscription_ID"));
}
}
myCmd = new SqlCommand("INSERT INTO SubscriptionCompany (Subscription_ID, Company_ID) VALUES (@Subscription_ID, @Company_ID)", conn);
parameter = new SqlParameter("@Subscription_ID", TestSubscriptionID); myCmd.Parameters.Add(parameter);
parameter = new SqlParameter("@Company_ID", KnownCompanyId); myCmd.Parameters.Add(parameter);
myCmd.ExecuteNonQuery();
What the heck is going on here? Did my command var just get tired???
What clued me to the "fix" was I noticed in my tracing that in my "read the id" block, my cmd.Parameters block had only ONE parameter in it, the 2nd one added, and when I forced the first cmd.Parameters.Add line to execute again, the number of parameters in the list dropped to 0. That's what prompted me to try a method level SqlCommand...cause I had the crazy idea that my cmd was tired... Imagine my shock when I apparently turned out to be right!
Edit: I'm not recycling any objects here - just the variable reference itself (static SqlCommand at the class level). My apologies for the earlier confusion in my wording of the question.