2016-12-06 48 views
0

我有兩個mysql TABLES - ORDERORDER_DETAILS關係是一個訂單有很多order_details。當通過循環插入時,變量已經被定義錯誤

創建訂單後,我得到最後插入的ID,我需要通過for循環插入最後插入的最後一個訂單ID的訂單詳細信息。但在這裏它是具有一個以上的訂單細節時

@order_id已經被定義

的消息。如果它是一個訂單的細節,它的作品。

如何在此處定義此訂單ID?這是一個錯誤的方式?這裏是我的代碼:

private void button2_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     DateTime localDate = DateTime.Now; 
     MydbConnection db = new MydbConnection(); 
     MySqlConnection con = db.connection(); 
     MySqlCommand cmd = new MySqlCommand(); 
     cmd.CommandText = "insert into orders (created) values(@localDate)"; 
     cmd.Parameters.AddWithValue("@localDate", localDate); 
     cmd.Connection = con; 
     con.Open(); 
     cmd.ExecuteNonQuery(); 
     long lastId = cmd.LastInsertedId;//Last inserted id 

     for (int i = 0; i < listView3.Items.Count; i++) 
     { 
      cmd.CommandText = "insert into order_details (order_id,product_id,qty) values(@order_id,@product_id,@qty)"; 
      cmd.Parameters.AddWithValue("@order_id", lastId); 
      cmd.Parameters.AddWithValue("@product_id", 1); 
      cmd.Parameters.AddWithValue("@qty", listView3.Items[i].SubItems[1]); 
      cmd.ExecuteNonQuery(); 
     } 
    } 
    catch (Exception es) { 
     MessageBox.Show("Order not saved! "+es.Message); 
    } 
} 
+0

嘗試在循環內創建一個新的命令對象。 –

+0

把這個'cmd = new MySqlCommand();'也放在循環中。 –

+0

我也是這麼做的。:( – user3722956

回答

1

你不能一直添加相同的命令參數。相反,爲什麼不能重新使用它們:

private void button2_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     DateTime localDate = DateTime.Now; 
     MydbConnection db = new MydbConnection(); 
     MySqlConnection con = db.connection(); 
     MySqlCommand cmd = new MySqlCommand(); 
     cmd.CommandText = "insert into orders (created) values(@localDate)"; 
     cmd.Parameters.AddWithValue("@localDate", localDate); 
     cmd.Connection = con; 
     con.Open(); 
     cmd.ExecuteNonQuery(); 
     long lastId = cmd.LastInsertedId;//Last inserted id 

     cmd.CommandText = "insert into order_details (order_id,product_id,qty) values(@order_id,@product_id,@qty)"; 
     MySqlCommandParameter orderIdParam, productIdParam, qtyParam; 
     for (int i = 0; i < listView3.Items.Count; i++) 
     { 
      if (i == 0) 
      { 
       orderIdParam = cmd.Parameters.AddWithValue("@order_id", lastId); 
       productIdParam = cmd.Parameters.AddWithValue("@product_id", 1); 
       qtyParam = cmd.Parameters.AddWithValue("@qty", listView3.Items[i].SubItems[1]); 
      } 
      else 
      { 
       orderIdParam.Value = lastId; 
       productIdParam.Value = 1; 
       qtyParam.Value = listView3.Items[i].SubItems[1]; 
      } 

      cmd.ExecuteNonQuery(); 
     } 
    } 
    catch (Exception es) { 
     MessageBox.Show("Order not saved! "+es.Message); 
    } 
} 

注:我還沒有實際測試此代碼,並可能有錯誤的類型和成員名稱MySqlCommandParameterMySqlCommandParameter.Value但你還是應該明白我的意思。

它可能會更好的編碼習慣Add參數第一(進入循環前),而不是在循環而不是使用AddWithValue第一個循環迭代if塊。您也可以考慮Clear - 在命令上收集參數,並在每次迭代中調用AddWithValue。最終,我認爲最好重新使用這些參數 - 當然最好每次迭代創建一個新的MySqlCommand實例 - 可能會有數千次迭代!

+1

什麼是MySqlCommandParameter的參考 – user3722956

+0

我不知道基本上它是無論什麼類型都是由'AddWithValue'返回的,因此我注意到類型名稱可能是錯誤的。看起來非常類似於此,但:https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparameter(v=vs.110).aspx – Xharlie

2

每次您撥打cmd.Parameters.AddWithValue時,都需要添加一個參數。當您使用相同名稱的參數調用它兩次或更多時,會出現重複的參數。

當您listView3.Items.Count至少包含兩個元素,你的代碼將添加複製@order_id@product_id@qty

您需要在每次迭代時重新創建MySqlCommand cmd,或者在參數已添加時更改參數的值。

第一種方法更容易出錯。至少因爲您不會使用以前使用中留下的其他數據(在循環之前添加的@localDate參數,否則該參數也會傳遞到數據庫)。

for (int i = 0; i < listView3.Items.Count; i++) 
    { 
     cmd = new MySqlCommand(); 
     cmd.Connection = con; 
     cmd.CommandText = "insert into order_details (order_id,product_id,qty) values(@order_id,@product_id,@qty)"; 
     cmd.Parameters.AddWithValue("@order_id", lastId); 
     cmd.Parameters.AddWithValue("@product_id", 1); 
     cmd.Parameters.AddWithValue("@qty", listView3.Items[i].SubItems[1]); 
     cmd.ExecuteNonQuery(); 
    } 
+0

我不會推薦這樣做。當參數可以被重用時,爲每個循環迭代創建一個新的'MySqlCommand'實例是非常浪費的 - 可能有成千上萬的循環迭代,並且所有這些實例將不得不等待垃圾收集! – Xharlie

+1

@Xharlie這一切都取決於如果他需要經常創建大量的請求,這種方法不是最優的,但是如果幾個請求很少發生,那麼這是一個關於納秒級的問題,不值得談論它。代碼的簡單性和可維護性會更好。 – lorond

1

首先,在評論中暗示,你需要一種方法來消除在循環的前一次迭代添加的參數:

cmd.Parameters.Clear(); 

放置cmd.ExecuteNonQuery(後)會替您。但要小心! SQL連接和SQL命令.NET基本類型實現了IDisposable,當你完成它們以避免連接池阻塞之類的事情時,你應該正確地廢棄它們。我最近不得不從一個管理不善的一次性項目中拯救一箇舊項目,並且a)這是一個痛苦,但是b)結果是一個更快,更可靠的應用程序。當你解決了你目前的問題時,你可能會想到這個問題。

相關問題