2015-10-28 4 views
0

я получаю ошибкуSqlTransaction на множественном запросе вставки

«Это SqlTransaction завершил, это уже не»

, а множественная вставка в одной таблице

mclDb.trans = mclDb.mCon.BeginTransaction(); 
try 
         { 
          foreach (DataGridViewRow dgvRow in dgvDetail.Rows) // get rows in details 
          { 
           ht.Clear(); 
           string dtlPoCode = dgvRow.Cells[2].Value.ToString(); 
           if (poCode == dtlPoCode) // check if po code matches 
           { 
            ht.Add("dtlPoCode", dtlPoCode); 
            ht.Add("dtlPoLine", dgvRow.Cells[3].Value.ToString()); 
            ht.Add("dtlwhouse", dgvRow.Cells[12].Value.ToString()); 
            ht.Add("dtlSkuCode", dgvRow.Cells[4].Value.ToString()); 
            ht.Add("dtlUom", dgvRow.Cells[6].Value.ToString()); 
            ht.Add("dtlmrQty", dgvRow.Cells[7].Value.ToString()); 
            ht.Add("dtlBCode", dgvRow.Cells[10].Value.ToString()); 
            ht.Add("dtlBExp", dgvRow.Cells[11].Value.ToString()); 
            ht.Add("dtlBin", dgvRow.Cells[9].Value.ToString()); 
            ht.Add("custPoCode", custPoCode); 
            ht.Add("grnCode", grnCode); 
            ht.Add("refCode", refCode); 

            mclDb.IUD(ht); 
           }         
          } 
          MessageBox.Show("Transaction Complete"); 
          mclDb.trans.Commit(); 
         } 
         catch (Exception error) 
         { 
          MessageBox.Show(error.Message, "Error Encountered", MessageBoxButtons.OK, MessageBoxIcon.Error); mclDb.trans.Rollback(); 
         } 

здесь мой метод ВМС

public void IUD(Hashtable ht) 
    { 
     try 
     { 
      Connect(); 
      string cmd = ""; 
      cmd = mStatements.getQuery(ht); 
      mAdptr = new SqlDataAdapter(cmd,mCon); 
      ds = new DataSet(); 
      mAdptr.Fill(ds); 
     } 
     catch (Exception Ex) 
     { 
      throw new Exception(Ex.Message); 
     } 
    } 

и мой метод GetQuery

public string getQuery(Hashtable ht) 
    { 
     StringBuilder qry = new StringBuilder(); 
     qry.Append(" Insert into mTable values "); 
     qry.Append(" ('" + ht["custPoCode"] + "','" + ht["dtlPoCode"] + "', "); 
     qry.Append(" " + ht["dtlPoLine"] + ",'" + ht["dtlwhouse"] + "', "); 
     qry.Append(" '" + ht["dtlSkuCode"] + "','" + ht["dtlUom"] + "', "); 
     qry.Append(" " + ht["dtlmrQty"] + ",'" + ht["grnCode"] + "', "); 
     qry.Append(" '" + ht["refCode"] + "','" + ht["dtlBCode"] + "', "); 
     qry.Append(" '" + ht["dtlBExp"] + "','" + ht["dtlBin"] + "', "); 
     qry.Append(" '" + ht["dtlmrQty"] + "','') "); 
     return qry.ToString(); 
    } 

количество строк, которые будут вставлены в таблице будет зависеть от того, сколько строк выбираются в dgvDetail (который является DataGridView)

любые предложения в том, как использовать SqlTransaction на мои коды? ТИА

+0

Внутри 'UID' метод, что делает метод' Connect'? Также почему адаптер данных, вы хотите выполнить запрос sql sql, правильно? –

+0

@IvanStoev Connect на самом деле является моим методом подключения к базе данных и адаптера, поэтому я также могу использовать запрос выбора для извлечения данных в datagrids – Isaiah

+0

Но он уже будет открыт, иначе строка 'mclDb.trans = mclDb.mCon.BeginTransaction(); 'потерпит неудачу –

ответ

0

Есть два подхода к этой проблеме,

Подход 1:

  • Доведите транзакции вне цикла Еогеаспа, в качестве последнего оператора в блоке Try, который обеспечивал бы что вы совершаете все за один раз, но для этого вам нужно еще несколько изменений:

    • Привести инициирование транзакции также в блок try
    • Using блок должен быть использован для создания транзакции, так как она будет автоматически располагать контекст транзакции после использования
    • Принесите этот вызов слишком вне цикла Еогеаспа - mclDb.IUD(ht);
    • метода
    • Makle ВМС принимает List<HashTable>
    • процесс всех HashTable в Списке создать строки в наборе данных и выполнить все вставки/обновления за один раз, используя объект Adapter, каким образом должен использоваться адаптер, поскольку он является частью отключенной архитектуры.
    • Возможно, вам потребуется изменение в запроса для обеспечения что соответствующие значения набора данных заполняются во время выполнения, проверьте ссылку Using SqlDataAdapter to insert a row

    • Infact первым его важно создать Dataset, Datatable схему, используя Select заявление и с помощью Adapter.Fill

    • Также обратите внимание на выполнение DML вам нужно , Adapter.Update, в отличие от Fill, который вы использовали в исходном коде, который только означает для выполнения запроса Select

подход 2:

Принесите даже инициализации транзакции внутри цикла foreach, что-то вроде:

foreach (DataGridViewRow dgvRow in dgvDetail.Rows) // get rows in details 
{ 
    mclDb.trans = mclDb.mCon.BeginTransaction(); 

Теперь оставшийся код может оставаться таким же, это для каждого хода в foreach цикле вы вставки внутри контекст транзакции

Выбор за вами Я бы предпочел первый, так как DataAdpater предназначен для выполнения массового выполнения DML для всех изменений в пределах Dataset, все может иметь место в заданном t ransaction context и exception будут выброшены при любом нарушении.

+0

ОК, я попробую первый, спасибо – Isaiah

+0

Проверьте сам подход 1, есть несколько ошибок в исходном коде, исправьте их, чтобы все работало должным образом –

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