2008-10-08 4 views
2

Заменяет Вопрос: Update multiple rows into SQL tableМножественные DB Обновления:

Вот фрагмент кода, чтобы обновить результаты экзамена набор. Структура DB дана, но я могу представить Хранимые процедуры для включения (которые являются болью для изменения, поэтому я сохраняю это до конца.)

Вопрос: Существует ли лучший способ использования SQL-сервера v 2005. , net 2.0?

string update = @"UPDATE dbo.STUDENTAnswers 
           SET [email protected] 
           WHERE StudentID [email protected] and QuestionNum [email protected]"; 
      SqlCommand updateCommand = new SqlCommand(update, conn); 
      conn.Open(); 

      string uid = Session["uid"].ToString(); 
      for (int i= tempStart; i <= tempEnd; i++) 
      { 
       updateCommand.Parameters.Clear(); 
       updateCommand.Parameters.AddWithValue("@ID",uid); 
       updateCommand.Parameters.AddWithValue("@qnum",i); 
       updateCommand.Parameters.AddWithValue("@answer", Request.Form[i.ToString()]); 
       try 
       { 
        updateCommand.ExecuteNonQuery(); 
       } 
       catch { } 
      } 

ответ

4

Несколько вещей выделяются:

  • Вы не показать, где SqlConnection конкретизируется, так что не ясно, что вы утилизации его правильно.

  • Вы не должны глотать исключения в цикле - лучше обрабатывать их в обработчике исключений верхнего уровня.

  • Вы создаете новые параметры на каждой итерации через цикл - вы можете просто повторно использовать параметры.

Сведя вместе это может выглядеть следующим образом (если вы не хотите использовать транзакцию, т.е. не волнует, если некоторые, но не все обновления успеха):

using (SqlConnection conn = new SqlConnection(connectionString)) 
{ 
    conn.Open(); 
    using (SqlCommand updateCommand = new SqlCommand(update, conn)) 
    { 
     string uid = Session["uid"].ToString(); 
     updateCommand.Parameters.AddWithValue("@ID", uid); 
     updateCommand.Parameters.AddWithValue("@qnum", i); 
     updateCommand.Parameters.Add("@answer", System.Data.SqlDbType.VarChar); 
     for (int i = tempStart; i <= tempEnd; i++) 
     { 
      updateCommand.Parameters["@answer"] = Request.Form[i.ToString()]; 
      updateCommand.ExecuteNonQuery(); 
     } 
    } 
} 

или использовать транзакцию, чтобы гарантировать, что все или ничего:

using (SqlConnection conn = new SqlConnection(connectionString)) 
{ 
    conn.Open(); 
    using (SqlTransaction transaction = conn.BeginTransaction()) 
    { 
     using (SqlCommand updateCommand = new SqlCommand(update, conn, transaction)) 
     { 
      string uid = Session["uid"].ToString(); 
      updateCommand.Parameters.AddWithValue("@ID", uid); 
      updateCommand.Parameters.AddWithValue("@qnum", i); 
      updateCommand.Parameters.Add("@answer", System.Data.SqlDbType.VarChar); 
      for (int i = tempStart; i <= tempEnd; i++) 
      { 
       updateCommand.Parameters["@answer"] = Request.Form[i.ToString()]; 
       updateCommand.ExecuteNonQuery(); 
      } 
      transaction.Commit(); 
     } 
    } // Transaction will be disposed and rolled back here if an exception is thrown 
} 

Наконец, еще одна проблема заключается в том, что вы смешиваете код пользовательского интерфейса (например, Request.Form) с кодом доступа к данным. Было бы более модульным и проверяемым, чтобы отделить их - например, разделяя ваше приложение на интерфейсы пользовательского интерфейса, бизнес-логики и доступа к данным.

-1

испускают одно обновление, который идет против таблицы значений:

UPDATE s SET ANSWER=a FROM dbo.STUDENTAnswers s JOIN (
    SELECT 1 as q, 'answer1' as a 
    UNION ALL SELECT 2, 'answer2' -- etc... 
) x ON s.QuestionNum=x.q AND [email protected] 

так что вы просто положить это вместе, как это:

using(SqlCommand updateCommand = new SqlCommand()) { 
    updateCommand.CommandType = CommandType.Text; 
    updateCommand.Connection = conn; 
    if (cn.State != ConnectionState.Open) conn.Open(); 

    StringBuilder sb = new StringBuilder("UPDATE s SET ANSWER=a FROM dbo.STUDENTAnswers s JOIN ("); 
    string fmt = "SELECT {0} as q, @A{0} as a"; 
    for(int i=tempStart; i<tempEnd; i++) { 
    sb.AppendFormat(fmt, i); 
    fmt=" UNION ALL SELECT {0},@A{0}"; 
    updateCommand.Parameters.AddWithValue("@A"+i.ToString(), Request.Form[i.ToString()]); 
    } 
    sb.Append(") x ON s.QuestionNum=x.q AND [email protected]"); 
    updateCommand.CommandText = sb.ToString(); 
    updateCommand.Parameters.AddWithValue("@ID", uid); 
    updateCommand.ExecuteNonQuery(); 
} 

Это имеет преимущества будучи все остальные ничего не работает (например, если вы завернули несколько обновлений в транзакции) и будет работать быстрее с:

  • Таблица и соответствующие индексы просматриваются/обновляется один раз
  • Вы платите только за время ожидания между приложением и сервером базы данных один раз, а не на каждом обновлении
0

Проблема, я вижу, когда ты открывают ваше соединение.

Я бы, по крайней мере, до того, как каждое обновление вызовет открытое, а затем закроет соединение после обновления.

Если ваша петля требует времени для выполнения, ваше соединение будет открыто в течение длительного времени.

Это хорошее правило никогда не открывать вашу команду, пока вам это не понадобится.

+0

Loop работает примерно 30 раз за каждый ответ. Мое мышление состояло в том, что я сохраню открытие и закрытие 30 раз. Я здесь не прав? – 2008-10-08 19:49:16

+0

Я согласен, я предпочел бы иметь открытое соединение для того, чтобы цикл работал, а не открывать и закрывать соединение N раз. – palmsey 2008-10-08 20:45:56

0

Вы можете навалом вставить с помощью OpenXML. Создайте XML-документ, содержащий все ваши вопросы и ответы, и используйте его для вставки значений.

Редактировать: Если вы придерживаетесь своего текущего решения, я бы по крайней мере обернул ваши SqlConnection и SqlCommand в используемом блоке, чтобы убедиться, что они удалены.

2

Для 30 обновлений, я думаю, что вы на правильном пути, хотя комментарий о необходимости использования около updateCommand верен.

Мы обнаружили, что наиболее эффективный способ делать массовые обновления (> 100 строк) осуществляется с помощью класса SqlBulkCopy во временную таблицу, за которой следует вызов хранимой процедуры для заполнения таблицы в реальном времени.

Смежные вопросы