我有两个mysql TABLES
- ORDER
和ORDER_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 :(得分: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();
}
答案 1 :(得分: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);
}
}
注意:我实际上没有测试过此代码,可能包含MySqlCommandParameter
和MySqlCommandParameter.Value
的错误类型和成员名称,但您仍然可以理解。
首先在Add
参数(在进入循环之前)并且在循环中没有if
块而不是在第一个循环中使用AddWithValue
可能是更好的编码实践迭代。您还可以在命令中考虑Clear
- 参数集合,并在每次迭代时调用AddWithValue
。最终,我认为最好重新使用这些参数 - 当然比每次迭代创建MySqlCommand
的新实例更可取 - 可能会有数千次迭代!
答案 2 :(得分:1)
首先,正如评论中暗示的那样,您需要一种方法来删除在循环的上一次迭代中添加的参数:
cmd.Parameters.Clear();
放在cmd.ExecuteNonQuery()之后会为你做这件事。但要小心! SQL连接和SQL命令,.NET基类型实现了IDisposable,当你完成它们时你应该正确地设置它们以避免连接池阻塞之类的事情。我最近不得不从管理不善的一次性用品中拯救一个旧项目,并且a)这是一个痛苦但b)结果是一个更快,更可靠的应用程序。当你解决了当前的问题时,你可能想要了解它。