В моем тестовом проекте у меня есть статический класс FixtureSetup, который я использую для настройки данных интеграционного тестирования для проверки.
Я использую одни и те же переменные SqlCommand и SqlParameter (а не сам объект) в этом классе, многократно, используя одни и те же ссылки на переменные снова и снова, каждый раз присваивая новые объекты SqlCommand и SqlParameter. Само мое соединение создается один раз и передается в методы, выполняющие настройку, поэтому каждая настройка использует свою собственную отдельную ссылку на подключение, и хотя одно и то же соединение используется несколько раз, оно всегда в линейной последовательности.
В одном из таких методов я столкнулся с очень странной ситуацией, когда моя переменная SqlCommand, похоже, просто устала.
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();
В приведенном выше примере в последней показанной строке, проделав то же самое, что я сделал буквально в десятках других мест (вставьте данные, прочтите столбец идентификатора и запишите его), я получу следующее:
SetUp: System.InvalidOperationException: ExecuteNonQuery требует открытого и доступного соединения. Текущее состояние соединения закрыто. в System.Data.SqlClient.SqlConnection.GetOpenConnection (метод String)
НО - замените cmd на новую переменную myCmd, и все работает нормально!
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();
Что, черт возьми, здесь происходит? Моя команда var просто устала ???
Что подсказало мне «исправление», так это то, что я заметил при трассировке, что в моем блоке «read the id» мой блок cmd.Parameters содержал только ОДИН параметр, второй добавлен, и когда я принудительно использовал первый cmd.Parameters. .Добавьте строку для повторного выполнения, количество параметров в списке упало до 0. Это и побудило меня попробовать метод уровня SqlCommand ... потому что у меня была безумная идея, что мой cmd устал ... Представьте мой шок, когда я видимо оказался прав!
Изменить: я не использую здесь какие-либо объекты - просто ссылку на переменную (статический SqlCommand на уровне класса). Приношу свои извинения за ранее ошибочную формулировку вопроса.