程序无法正确保存数值:十进制计算结果异常求助
咱们一步步来梳理你遇到的问题,从代码里能看到几个明显的错误,还有一些潜在的坑:
1. 输入框重复引用(最直接的错误)
看你的按钮点击事件代码:
materialPrice = Decimal.Parse(txtMaterialUnitPrice.Text); purchasedWeight = Decimal.Parse(txtMaterialUnitPrice.Text);
你把单价和重量都从同一个文本框txtMaterialUnitPrice读取了!这显然不对,应该是单价从txtMaterialUnitPrice读,重量从对应的重量输入框(比如你可能命名重复了,应该是txtPurchasedWeight这类)读取,修正后:
materialPrice = Decimal.Parse(txtMaterialUnitPrice.Text); purchasedWeight = Decimal.Parse(txtPurchasedWeight.Text); // 替换为重量对应的文本框名
这一步错了的话,计算出来的根本不是「单价×重量」,完全不符合预期。
2. 十进制解析的文化适配问题
你输入的是4,5、6,5这种用逗号做小数点分隔符的格式,而Decimal.Parse默认会使用当前线程的系统文化设置。如果你的系统文化是用点(.)做小数点的(比如中文、英文系统),直接解析要么抛出异常,要么错误地把逗号当成千位分隔符(比如4,5被解析成45)。
解决方法是指定支持逗号小数点的文化(比如土耳其tr-TR、法语fr-FR,根据你的实际地区):
var culture = CultureInfo.GetCultureInfo("tr-TR"); // 适配逗号作为小数点的地区 materialPrice = Decimal.Parse(txtMaterialUnitPrice.Text, culture); purchasedWeight = Decimal.Parse(txtPurchasedWeight.Text, culture);
3. 数据库插入时的变量错误
看你的Insert方法里的SQL语句:
String query = string.Format("INSERT INTO sales(...) VALUES ('{0}', '{1}' , '{2}', '{3}','{4}','{5}','{6}','{7}','{8}','{9}')", cID, cNameSurname, cPlate, mID, mName, mPrice, pWeight, cleanAmount, dt, explanation);
你方法参数传的是totalPrice,但SQL里却用了cleanAmount!这个cleanAmount变量未定义,大概率是一个被截断的整数(比如把29.25转成了29),导致插入数据库的数值错误。必须把cleanAmount改成totalPrice:
String query = string.Format("INSERT INTO sales(...) VALUES ('{0}', '{1}' , '{2}', '{3}','{4}','{5}','{6}','{7}','{8}','{9}')", cID, cNameSurname, cPlate, mID, mName, mPrice, pWeight, totalPrice, dt, explanation);
4. 数据库字段类型检查
检查你的sales表中TotalPrice字段的类型:
- 如果是
INT类型,插入时会自动截断小数部分,29.25就会变成29; - 必须改成
DECIMAL类型,并且设置足够的精度和小数位数,比如DECIMAL(10,2)(表示总共10位,其中2位小数),这样才能正确存储带小数的数值。
5. 避免SQL注入(重要优化)
你现在用string.Format拼接SQL语句,存在严重的SQL注入风险,同时也容易因为类型转换出现问题。建议改用参数化查询:
public static Sales Insert(int cID, String cNameSurname, String cPlate, int mID, String mName, Decimal mPrice, Decimal pWeight, Decimal totalPrice, String dt, String explanation) { String query = @"INSERT INTO sales(CustomerID,CustomerNameSurname,CustomerPlate,MaterialID,MaterialType,MaterialPrice,PurchasedWeight,TotalPrice,SalesDate,Explanation) VALUES (@cID, @cNameSurname, @cPlate, @mID, @mName, @mPrice, @pWeight, @totalPrice, @dt, @explanation)"; MySqlCommand cmd = new MySqlCommand(query, DB.dbConn); cmd.Parameters.AddWithValue("@cID", cID); cmd.Parameters.AddWithValue("@cNameSurname", cNameSurname); cmd.Parameters.AddWithValue("@cPlate", cPlate); cmd.Parameters.AddWithValue("@mID", mID); cmd.Parameters.AddWithValue("@mName", mName); cmd.Parameters.AddWithValue("@mPrice", mPrice); cmd.Parameters.AddWithValue("@pWeight", pWeight); cmd.Parameters.AddWithValue("@totalPrice", totalPrice); cmd.Parameters.AddWithValue("@dt", dt); cmd.Parameters.AddWithValue("@explanation", explanation); DB.dbConn.Open(); cmd.ExecuteNonQuery(); int id = (int)cmd.LastInsertedId; Sales sale = new Sales(id, cID, cNameSurname, cPlate, mID, mName, mPrice, pWeight, totalPrice, dt, explanation); DB.dbConn.Close(); return sale; }
参数化查询不仅更安全,还能自动处理数值类型的转换,避免字符串拼接导致的格式错误。
总结修复步骤
- 修正输入框引用,确保单价和重量从不同的文本框读取;
- 调整
Decimal.Parse的文化设置,适配逗号作为小数点的输入格式; - 把Insert方法里的
cleanAmount替换为totalPrice; - 检查数据库
TotalPrice字段类型,确保是DECIMAL类型且小数位数足够; - 改用参数化查询避免SQL注入和类型转换问题。
按照上面的步骤修改后,应该就能正确计算并保存29.25这个数值了。
内容的提问来源于stack exchange,提问作者ersnbck

