You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 18:17:48