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

WPF TextBox输入Double/Float存MySQL异常与输入限制解决方案

问题背景

应用内设置两个文本框,分别用于配置儿童票、成人票价格。文本框内容变更时会触发textbox_ValueChanged事件,执行priceChanged()方法将价格写入MySQL数据库,存储价格的字段类型为double。
输入整数时功能运行正常,输入浮点数时出现两类异常:

  • 按顺序输入"5"、","、"5"时:输入第二个"5"后程序立即崩溃,崩溃位置为数据库执行代码cmd.ExecuteNonQuery();,报错信息:

Data truncated for column 'adults' at row 1

  • 按顺序输入"5"、"."、"5"时:程序无崩溃,但存入数据库的数值会丢失小数点,例如输入"5.5"实际存储为"55"。

原有数据库保存代码如下:

public static void updatePrice(double _adults, double _children)
{
    MySqlConnection cnn = OpenCnn();
    MySqlCommand cmd = new MySqlCommand("UPDATE price SET adults = '" + _adults + "', children = '" + _children + "';", cnn);
    cmd.ExecuteNonQuery();
}

原有调用逻辑代码如下:

private void priceChanged()
{
    double adultPrice;
    double childPrice;

    try
    {
        adultPrice = Convert.ToDouble(adultPriceTextbox.Text);
    }
    catch
    {
        adultPrice = 0.0;
    }
    try
    {
        childPrice = Convert.ToDouble(childPriceTextbox.Text);
    }
    catch
    {
        childPrice = 0.0;
    }
    DatabaseInterface.updatePrice(adultPrice, childPrice);
}

补充运行环境说明:程序部署在德国区域,当地小数书写默认使用,作为分隔符,而非.。需求为实现支持整数、浮点数输入的价格文本框,同时增加输入屏蔽,禁止输入字母类字符,仅允许输入数字、.、,符号。

问题根因
  • 数据库操作采用字符串拼接SQL的写法,未使用参数化查询:德国区域下double类型转字符串默认以,作为小数分隔符,拼接进SQL语句后,MySQL会将逗号识别为字段值分隔符,直接触发值截断报错;如果用户输入.作为小数分隔符,不符合本地默认格式规则,转换时会直接忽略小数点,导致5.5被识别为55存入数据库。
  • 文本框未做输入校验与过滤,未对用户输入的两种小数分隔符做统一兼容处理。
  • 数值转换未显式指定区域文化规则,默认依赖系统区域配置,遇到非默认分隔符时转换逻辑异常,且用try-catch做转换判断性能较差。
实现方案

1. 输入屏蔽与自动兼容

给两个价格文本框绑定统一的KeyPress事件,仅允许输入数字、控制字符(退格等)、单个小数分隔符,同时自动将用户输入的.替换为德国区域默认的,,兼容不同输入习惯:

// 窗体初始化时绑定事件
adultPriceTextbox.KeyPress += PriceTextBox_KeyPress;
childPriceTextbox.KeyPress += PriceTextBox_KeyPress;

private void PriceTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
    TextBox targetTb = sender as TextBox;
    // 允许数字、控制字符输入
    if (char.IsControl(e.KeyChar) || char.IsDigit(e.KeyChar))
    {
        e.Handled = false;
        return;
    }
    // 仅允许输入一个小数分隔符,自动统一为逗号适配德国区域格式
    if ((e.KeyChar == ',' || e.KeyChar == '.') && 
        !targetTb.Text.Contains(',') && !targetTb.Text.Contains('.'))
    {
        e.KeyChar = ',';
        e.Handled = false;
        return;
    }
    // 其余字符全部拦截
    e.Handled = true;
}

2. 修正数值解析逻辑

使用double.TryParse显式指定德国区域文化做数值转换,相比try-catch性能更高,同时预处理输入内容,进一步兼容分隔符输入场景:

private void priceChanged()
{
    CultureInfo deCulture = new CultureInfo("de-DE");
    double adultPrice = 0.0;
    double childPrice = 0.0;

    // 二次兼容:把输入中残留的点替换为逗号,避免解析异常
    string adultInput = adultPriceTextbox.Text.Trim().Replace('.', ',');
    string childInput = childPriceTextbox.Text.Trim().Replace('.', ',');

    double.TryParse(adultInput, NumberStyles.Float, deCulture, out adultPrice);
    double.TryParse(childInput, NumberStyles.Float, deCulture, out childPrice);

    DatabaseInterface.updatePrice(adultPrice, childPrice);
}

3. 数据库层改用参数化查询(核心修复)

彻底替换字符串拼接的SQL写法,通过参数传值,由数据库驱动直接处理double类型,不存在字符串格式不匹配问题,同时可避免SQL注入风险:

public static void updatePrice(double _adults, double _children)
{
    // using语句自动释放连接资源,避免连接泄漏
    using (MySqlConnection cnn = OpenCnn())
    {
        string updateSql = "UPDATE price SET adults = @adults, children = @children;";
        using (MySqlCommand cmd = new MySqlCommand(updateSql, cnn))
        {
            // 参数直接传入double类型值,无需手动转字符串
            cmd.Parameters.AddWithValue("@adults", _adults);
            cmd.Parameters.AddWithValue("@children", _children);
            cmd.ExecuteNonQuery();
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 11:06:19