ASP.NET WebForms项目SQL数据库产品库存仅扣减1问题求解
问题根源
你的bug是典型的ASP.NET WebForms页面生命周期执行顺序错误导致的:你没有在绑定下拉列表的代码外层加!IsPostBack判断,导致每次页面回发(比如点击下单按钮触发提交操作)时,都会先重新执行下拉列表的绑定逻辑,把用户选中的值重置为默认的第一个选项(也就是1),之后才会执行你写的扣减库存的代码,所以永远只能扣减1。
修复方案
第一步:给下拉列表绑定逻辑加回发判断
找到你WebForm2的Page_Load方法,把下拉列表绑定、产品信息查询的代码都放到if (!IsPostBack)的代码块里,修改后的代码如下:
protected void Page_Load(object sender, EventArgs e) { string productName = Request.QueryString["productname"]; txt_product13.Text = productName; // 只有首次加载页面时才绑定下拉列表,回发时不执行 if (!IsPostBack) { var dictionary = new Dictionary<string, object> { { "@ProductName", productName } }; var parameters = new DynamicParameters(dictionary); string CS = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString; using (var connection = new SqlConnection(CS)) { connection.Open(); var sql = "SELECT * FROM ProductsDB WHERE ProductName = @ProductName"; var product = connection.QuerySingle<Product>(sql, parameters); CultureInfo EuroCulture = new CultureInfo("fr-FR"); txt_productprice.Text = product.Price.ToString("c", EuroCulture); dropdownlist1.Items.Clear(); // 绑定前先清空原有选项,避免重复追加 for (int i = 1; i <= product.Quantity; i++) { dropdownlist1.Items.Add(new ListItem(i.ToString(), i.ToString())); } } } }
第二步:优化扣减库存代码的安全性和健壮性
你现在的扣减SQL拼接了数值,存在SQL注入风险,同时要加库存不足的校验,避免扣成负数,修改后的扣减代码如下:
// 下单按钮点击事件里的扣减逻辑 string productName = Request.QueryString["productname"]; // 优先取SelectedValue而不是Text,避免显示文本和值不一致的问题 int buyCount = Convert.ToInt32(dropdownlist1.SelectedValue); var dictionary = new Dictionary<string, object> { {"@ProductName", productName }, {"@BuyCount", buyCount } }; var parameters = new DynamicParameters(dictionary); string CS = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString; using (var connection = new SqlConnection(CS)) { connection.Open(); // 用参数化传购买数量,不要拼接字符串,同时加库存判断避免超卖 var sql = @"UPDATE ProductsDB SET Quantity = Quantity - @BuyCount WHERE ProductName = @ProductName AND Quantity >= @BuyCount"; int affectRows = connection.Execute(sql, parameters); if (affectRows == 0) { // 库存不足的提示逻辑 ClientScript.RegisterStartupScript(this.GetType(), "alert", "alert('库存不足,下单失败');", true); } else { // 下单成功的逻辑 ClientScript.RegisterStartupScript(this.GetType(), "alert", "alert('下单成功');", true); } // 不需要手动Close,using会自动释放连接 }
额外注意点
- 下拉列表取值优先用
SelectedValue而不是SelectedItem.Text,避免后续修改显示文本时出现取值错误 - 扣减库存时加
Quantity >= @BuyCount的判断可以防止超卖,避免库存出现负数 - 所有和用户输入相关的参数都要用参数化传递,不要直接拼接SQL,避免SQL注入漏洞
内容的提问来源于stack exchange,提问作者drjoker
相关产品推荐
相关产品推荐

