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

如何在现有C# SQL下单逻辑中实现订单配送司机轮循分配

实现方案

核心逻辑

轮循分配的核心是用「当前累计有效订单数对司机总数取模」得到索引,匹配对应司机即可,规则适配你的需求:

  • 先查询司机表获取所有正常可用的司机列表,按driverid升序排序保证轮循顺序固定
  • 统计当前已经生成的有效订单总数量(可自行过滤已取消等无效订单)
  • 计算索引:司机索引 = 总订单数 % 司机总数,刚好适配列表从0开始的下标规则,比如3个司机的场景:总订单数0取模得0对应driver1,总订单数2取模得2对应driver3,总订单数3取模得0回到driver1,完全符合轮循要求
  • 取出对应索引的driverid赋值给插入语句的司机字段即可

代码修改示例

在你原有的订单插入逻辑之前新增司机分配逻辑即可,同时建议将原有的SQL字符串拼接改为参数化查询,避免SQL注入风险:

string deliveryDate = DateTime.Now.AddDays(2).ToString("M/d/yyyy");
SqlConnection con = new SqlConnection(str);

// ========== 新增:轮循分配司机逻辑开始 ==========
con.Open();
// 1. 查询所有可用司机,按id排序保证轮循顺序固定,is_enabled为司机是否启用的标识,没有该字段可以去掉条件
SqlCommand driverCmd = new SqlCommand("SELECT driverid FROM Driver ORDER BY driverid ASC", con);
SqlDataAdapter driverDa = new SqlDataAdapter(driverCmd);
DataTable driverDt = new DataTable();
driverDa.Fill(driverDt);
int driverCount = driverDt.Rows.Count;
if(driverCount == 0){
    // 无可用司机的异常处理
    Response.Write("<script>alert('当前暂无可用配送司机,请稍后再试');</script>");
    con.Close();
    return;
}

// 2. 查询当前已有的有效订单总数
SqlCommand orderCountCmd = new SqlCommand("SELECT COUNT(*) FROM OrderDetails", con);
int totalOrderCount = Convert.ToInt32(orderCountCmd.ExecuteScalar());

// 3. 计算本次分配的司机索引
int driverIndex = totalOrderCount % driverCount;
string driverid = driverDt.Rows[driverIndex]["driverid"].ToString();
con.Close();
// ========== 新增:轮循分配司机逻辑结束 ==========

if (Session["buyitems"] != null && Session["Orderid"] != null)
{
    DataTable dt = (DataTable)Session["buyitems"];
    for (int i = 0; i <= dt.Rows.Count - 1; i++)
    {
        string pId = dt.Rows[i]["pid"].ToString();
        int pQuantity = Convert.ToInt16(dt.Rows[i]["pquantity"]);
        SqlDataAdapter sda = new SqlDataAdapter("Select Pquantity from ProductShirt where ProductId ='" + pId + "' ", con);
        DataTable dtbl = new DataTable();
        sda.Fill(dtbl);

        int quantity = Convert.ToInt32(dtbl.Rows[0][0]);
        if (quantity > 0)
        {
            con.Open();
            // 改为参数化查询避免SQL注入
            string insertSql = @"insert into OrderDetails(orderid,sno,productid,productname,price,quantity,orderdate,status,email,deliverydate,address, driverid) 
                                values(@orderid,@sno,@productid,@productname,@price,@quantity,@orderdate,'Pending',@email,@deliverydate,@address, @driverid)";
            SqlCommand cmd = new SqlCommand(insertSql, con);
            cmd.Parameters.AddWithValue("@orderid", Session["Orderid"].ToString());
            cmd.Parameters.AddWithValue("@sno", dt.Rows[i]["sno"]);
            cmd.Parameters.AddWithValue("@productid", dt.Rows[i]["pid"]);
            cmd.Parameters.AddWithValue("@productname", dt.Rows[i]["pname"].ToString());
            cmd.Parameters.AddWithValue("@price", Convert.ToInt32(dt.Rows[i]["pprice"]));
            cmd.Parameters.AddWithValue("@quantity", dt.Rows[i]["pquantity"]);
            cmd.Parameters.AddWithValue("@orderdate", DateTime.Now.ToString("M/d/yyyy"));
            cmd.Parameters.AddWithValue("@email", Session["username"].ToString());
            cmd.Parameters.AddWithValue("@deliverydate", deliveryDate);
            cmd.Parameters.AddWithValue("@address", TextBox1.Text);
            cmd.Parameters.AddWithValue("@driverid", driverid);

            cmd.ExecuteNonQuery();
            con.Close();
        }
    }

    decreaseQuantity();
    clearCart();
    Session["buyitems"] = null;
    Session["deliverydate"] = deliveryDate;
    Response.Redirect(url);
}
else
{
    Response.Redirect("AddtoCart.aspx");
}

高并发场景优化

如果站点订单并发量较高,可能出现多个请求同时查询到相同总订单数、分配到同一个司机的问题,可做如下优化:

  • 单独创建计数器表DispatchCounter,仅存储current_count整数字段记录轮询计数
  • 每次分配司机时先执行原子更新操作UPDATE DispatchCounter SET current_count = current_count + 1,再读取更新后的计数值计算司机索引,避免并发重复分配

内容的提问来源于stack exchange,提问作者MikeWizowski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 20:24:01