SqlDataReader и SqlCommand
У меня есть следующий код.
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
connection.Open();
SqlCommand select = new SqlCommand("SELECT RTRIM(LTRIM(PART_NO)) AS PART_NO, record FROM [RMAData].[dbo].[IMPORTING_ORDER_EDI] WHERE sessionID = '" + Session.SessionID + "'", connection);
SqlDataReader reader = select.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
if (!currentPart.IsActive)
{
// this part is not active, set the active flag in sql to 0
SqlCommand update = new SqlCommand("UPDATE [RMAData].[dbo].[IMPORTING_ORDER_EDI] SET valid = 0, active = 0 WHERE record = " + reader["record"].ToString() + ";", connection);
update.ExecuteNonQuery();
}
else
{
///blah
}
}
reader.Close();
}
}
Но это вызывает следующее исключение...
система.InvalidOperationException: уже есть открытый DataReader связан с этой командой, которая должна быть закрыта в первую очередь.
Мне нужно прочитать каждую возвращенную строку, сделать некоторую проверку данных и сделать обновление, если это необходимо, а затем перейти к следующей записи. Как я могу достичь этого, если я не могу использовать SqlCommand
, проходя через reader.Read()
?
3 ответа:
Альтернативой является не добавление MultipleActiveResultSets=True - для этого существует небольшое ограничение производительности - и поэтому что-то вроде этого:
using (SqlConnection connection = new ...)) { connection.Open(); SqlCommand select = new SqlCommand(...); SqlDataReader reader = select.ExecuteReader(); var toInactivate = new List<string>(); if (reader.HasRows) { while (reader.Read()) { if (!currentPart.IsActive) { toInactivate.Add(reader["record"].ToString()); } else { ///blah } } reader.Close(); } SqlCommand update = new SqlCommand("UPDATE ... SET valid = 0, active = 0 " + "WHERE record IN(" + string.Join(",", toInactivate) + ");", connection); update.ExecuteNonQuery(); }
, который имеет преимущество обновления всех необходимых записей в одном операторе SQL.
И, конечно, все это было бы намного аккуратнее, используя EF и Linq.
Может быть так же просто, как изменение строки соединения:
Добавить MultipleActiveResultSets=True к строке соединения
Вам нужно либо создать несколько экземпляров вашего соединения.
Как только одна команда может быть исключена против соединения вообще
или
сделайте так, как предлагает @grantThomas
или вы можете использовать множественное соединение следующим образомusing (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString)) { connection.Open(); SqlCommand select = new SqlCommand("SELECT RTRIM(LTRIM(PART_NO)) AS PART_NO, record FROM [RMAData].[dbo].[IMPORTING_ORDER_EDI] WHERE sessionID = '" + Session.SessionID + "'", connection); SqlDataReader reader = select.ExecuteReader(); if (reader.HasRows) { while (reader.Read()) { if (!currentPart.IsActive) { // this part is not active, set the active flag in sql to 0 using (SqlConnection connection1 = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString)) { SqlCommand update = new SqlCommand("UPDATE [RMAData].[dbo].[IMPORTING_ORDER_EDI] SET valid = 0, active = 0 WHERE record = " + reader["record"].ToString() + ";", connection1); update.ExecuteNonQuery(); } } else { ///blah } } reader.Close(); } }