2016-12-06 3 views
0

私は2つのmysqlを持っていますTABLES - ORDERORDER_DETAILS関係が1つの注文には多くのorder_detailsがあります。ループのために挿入するときに変数がすでに定義されています

注文を作成した後、私は最後に挿入されたIDを取得し、最後に挿入された最後の注文IDを持つ注文の詳細をforループを介して挿入する必要があります。しかし、ここでは、複数の注文の詳細を持つとき

@order_idがすでに

に定義されたメッセージを示しています。 1つの注文詳細であれば動作します。

ここでこの注文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の間違った種類とメンバー名を持っていますが、あなたはまだアイデアを得る必要があります。

最初のループ反復にAddWithValueを使用する代わりに、最初に(ループに入る前に)パラメータをAddに置き換え、ループ内に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に電話するたびに、もう1つのパラメータを追加します。同じ名前のパラメータで2回以上呼び出すと、重複したパラメータが表示されます。

listView3.Items.Countに少なくとも2つの要素が含まれている場合、コードには@order_id,@product_id@qtyが重複して追加されます。

各繰り返しでMySqlCommand cmdを再作成するか、既に追加したときにパラメータの値を変更する必要があります。

最初のアプローチはエラーが発生しやすくなります。あなたが前の使用法から残った他のデータ(ループの前に追加したパラメータ@localDate、それ以外の場合はデータベースにも渡されます)を使用しないためです。以下のためにそれを行うだろう)

cmd.Parameters.Clear(); 

cmd.ExecuteNonQuery(後に置か:コメントで示唆したよう

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

はまず、あなたは、ループの前の反復で追加パラメータを削除する方法が必要です君は。しかし、注意! SQL接続とSQLコマンドの.NETベース型ではIDisposableが実装されているため、接続プールブロッキングなどの問題を避けるためにそれらの処理が完了したら正しく処理する必要があります。私は最近、不十分に管理されたディスポーザブルから古いプロジェクトを救済しなければならなかった。それは痛みだったが、結果ははるかに高速で信頼性の高いアプリだった。あなたはあなたの現在の問題を解決したときにそれを調べることができます。

関連する問題