WinForm餐厅点餐系统:实现ListView选中项确认同步至另一ListView及SQL订单入库的技术求助
解决方案:餐厅点餐系统订单页面完善
我来帮你搞定这个点餐系统的两个核心功能——把选中菜品移到订单列表,还有把订单存到SQL数据库。先从你现有代码里的小问题入手,一步步优化:
1. 修正弹窗判断逻辑 & 实现ListView选中项转移
你的button2_Click方法里,没有正确捕获用户的弹窗选择,也没处理ListView项的转移逻辑。下面是修正后的完整代码:
private void button2_Click(object sender, EventArgs e) { string message = "Add Selection To Order?"; string caption = "Confirm Order Addition"; MessageBoxButtons buttons = MessageBoxButtons.YesNo; // 捕获用户的弹窗选择结果 DialogResult result = MessageBox.Show(this, message, caption, buttons); if (result == DialogResult.Yes) { // 遍历listView1的选中项,复制到listView2 foreach (ListViewItem selectedItem in listView1.SelectedItems) { // 完整复制选中项的所有子项(包括ID、名称、价格等) ListViewItem newOrderItem = (ListViewItem)selectedItem.Clone(); listView2.Items.Add(newOrderItem); // 可选:如果需要从菜单列表移除已选中菜品,取消下面注释 // selectedItem.Remove(); } // 调用数据库存储逻辑,把订单存到SQL SaveOrderToDatabase(); } else if (result == DialogResult.No) { this.Close(); } }
关键细节:
- 原代码直接用
DialogResult == DialogResult.Yes是错误的,必须把MessageBox.Show的返回值赋值给变量后再判断,这才是用户的真实选择。 - 使用
Clone()方法可以完整复制ListViewItem的所有子项,避免手动拼接的麻烦。
2. 实现订单存入SQL数据库
首先假设你的数据库有两张核心表(如果没有需要先创建):
Orders:存储订单主信息,比如order_id(主键自增)、order_date、table_number(可选,比如餐桌号)等。OrderItems:存储订单明细,比如order_item_id、order_id(外键关联Orders)、menu_item_id、quantity、price等。
下面是负责存储订单的方法实现:
private void SaveOrderToDatabase() { // 使用using自动释放数据库连接,避免资源泄漏 using (SqlConnection sqlConnection = new SqlConnection(connection)) { sqlConnection.Open(); // 开启事务,确保订单主记录和明细要么全成功,要么全回滚,避免数据不一致 using (SqlTransaction transaction = sqlConnection.BeginTransaction()) { try { // 1. 插入订单主记录,并获取自动生成的order_id string insertOrderSql = "INSERT INTO Orders (order_date) OUTPUT INSERTED.order_id VALUES (@orderDate)"; using (SqlCommand orderCmd = new SqlCommand(insertOrderSql, sqlConnection, transaction)) { orderCmd.Parameters.AddWithValue("@orderDate", DateTime.Now); int orderId = (int)orderCmd.ExecuteScalar(); // 2. 遍历listView2,插入每条订单明细 foreach (ListViewItem item in listView2.Items) { string insertItemSql = @"INSERT INTO OrderItems (order_id, menu_item_id, quantity, price) VALUES (@orderId, @menuItemId, @quantity, @price)"; using (SqlCommand itemCmd = new SqlCommand(insertItemSql, sqlConnection, transaction)) { itemCmd.Parameters.AddWithValue("@orderId", orderId); itemCmd.Parameters.AddWithValue("@menuItemId", int.Parse(item.SubItems[0].Text)); itemCmd.Parameters.AddWithValue("@quantity", 1); // 默认数量为1,你可以加输入框让用户修改 itemCmd.Parameters.AddWithValue("@price", decimal.Parse(item.SubItems[3].Text)); itemCmd.ExecuteNonQuery(); } } // 提交事务,完成存储 transaction.Commit(); MessageBox.Show("订单已成功保存到数据库!"); } } catch (Exception ex) { // 出错时回滚所有操作 transaction.Rollback(); MessageBox.Show($"保存订单失败:{ex.Message}"); } } } }
关键说明:
- 用事务处理订单主记录和明细的插入,防止出现“只存了订单头,没存明细”的异常情况。
- 如果你的表结构和假设不同(比如有服务员ID、备注等),直接修改
INSERT语句的参数即可。 - 数量默认设为1,你可以在ListView里新增数量列,或者弹出输入框让用户自定义数量后再传入。
3. 额外优化建议
在buttonLunchMenu_Click方法里,同样用using管理数据库对象,避免资源泄漏,同时修正价格类型的读取(价格应该用decimal,原代码的GetInt32会丢失精度或报错):
private void buttonLunchMenu_Click(object sender, EventArgs e) { buttonViewMenu.Visible = false; button2.Visible = true; using (SqlConnection sqlConnection = new SqlConnection(connection)) { sqlConnection.Open(); string selectSql = "SELECT menu_item_id, menu_item_name, menu_item_stock, menu_item_price, menu_item_category FROM MenuItem"; using (SqlCommand selectLunchMenu = new SqlCommand(selectSql, sqlConnection)) { using (SqlDataReader reader = selectLunchMenu.ExecuteReader()) { listView1.Items.Clear(); while (reader.Read()) { ListViewItem lv = new ListViewItem(reader.GetInt32(0).ToString()); lv.SubItems.Add(reader.GetString(1)); lv.SubItems.Add(reader.GetInt32(2).ToString()); lv.SubItems.Add(reader.GetDecimal(3).ToString()); // 用GetDecimal读取价格,避免精度丢失 lv.SubItems.Add(reader.GetString(4)); listView1.Items.Add(lv); } } } } }
这样修改后,你的点餐系统就能完美实现选中菜品转移到订单列表,并且将订单完整存入SQL数据库了。
内容的提问来源于stack exchange,提问作者conorog247
相关产品推荐
相关产品推荐

