[研究]ASP.NET,WebForm,e.NewValues存入 DB 的 float 欄位後可能變了(一)
2025-04-28
環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19
********************************************************************************
最近碰到一個況狀,一個小數值,e.NewValues 存入DB 的 float 欄位後,幾乎都正常,但遇到一個值居然變了的情況;在 Visual Studio 2019 中 Debug,追蹤 DetailsView1_ItemUpdating() 的 e.NewValues 值到最後,都是正常的,但DB更新結果的值卻不符;研究了一下。float value = Convert.ToSingle(e.NewValues["Rate1"]); |
或
command.Parameters.AddWithValue("@Rate1", e.NewValues["Rate1"]);
|
因為 e.NewValues 裡面的值其實是 object,很可能已經經過一輪型別轉換(例如從 TextBox 字串變 float),過程中又有誤差。
decimal value = Convert.ToDecimal(e.NewValues["Rate1"]);
command.Parameters.Add("@Rate1", SqlDbType.Decimal).Value = value;
|
並且資料表欄位是 decimal(10,4)。
********************************************************************************
未何 DB 中欄位定義是 float,但是 ASP.NET WebForm 產出的 <asp:Parameter Name="Rate1" Type="Double" /> 中是 double ?
ChatGPT 說:
你的問題非常專業,來,我直接重點回答:
1. SQL Server 的 float 對應到 .NET 是 double
在 SQL Server 裡,float 是一種「近似數字」,但它沒有直接對應到 C# 裡的 float (C# 的 float 是 32-bit 喔)。
實際上:
SQL Server 的 float(53) (預設就是 53 位元的 float)→ 對應到 .NET C# 的 double(64-bit 浮點數)
SQL Server 的 real (低精度浮點)→ 才對應到 .NET C# 的 float(32-bit)
也就是說,SQL Server 的 float 預設就是高精度版本,所以 ASP.NET WebForm 在 Parameter 自動產生時,會設定成:
<asp:Parameter Name="Rate1" Type="Double" />
而不是 Type="Single"(Single 才是 .NET 的 float)
這是正確且預期的行為!
2. 微軟官方對應表(簡單版)
| SQL Server 資料型態 | .NET 型態 | asp:Parameter Type |
| float | System.Double | Double |
| real | System.Single | Single |
| decimal / numeric | System.Decimal | Decimal |
3. 但是!精度問題還是存在
即使 .NET 這邊是 double,但因為 SQL Server 的 float 是近似值(approximate),小數點附近會有細微誤差,這就是為什麼你會遇到像 0.58 變成 0.57 這種情形。
********************************************************************************
SQL Server 那些資料型別 是「近似值」(approximate numeric)
ChatGPT 說:只有兩種:
| 資料型別 | 說明 |
| float | 浮點數,近似值,精度高(通常是 53 位元,對應 .NET 的 double) |
| real | 浮點數,近似值,但精度比 float 低(對應 .NET 的 float) |
這兩個型別儲存的是「浮點表示」的數字,會有細微誤差,不是精確儲存小數位。
********************************************************************************
.NET Framework 裡,「近似值」(approximate numeric)的資料型別哪幾種
ChatGPT 說:只有兩種:
| .NET 型別 | 大小 | 精度 | 說明 |
| float (System.Single) | 32 位元(4 bytes) | 大約 7 位十進位有效數字 | 單精度浮點數(single-precision floating point) |
| double (System.Double) | 64 位元(8 bytes) | 大約 15~16 位十進位有效數字 | 雙精度浮點數(double-precision floating point) |
這兩種型別都是基於 IEEE 754 標準儲存方式,本質上是近似值,不是完全精確。
********************************************************************************
.NET Framework 數值型別分類圖
數值型別
├── 精確值 (Exact Numeric)
│ ├── 整數型 (Integer Types)
│ │ ├── byte (0 ~ 255)
│ │ ├── sbyte (-128 ~ 127)
│ │ ├── short (-32,768 ~ 32,767)
│ │ ├── ushort (0 ~ 65,535)
│ │ ├── int (-2^31 ~ 2^31-1)
│ │ ├── uint (0 ~ 2^32-1)
│ │ ├── long (-2^63 ~ 2^63-1)
│ │ └── ulong (0 ~ 2^64-1)
│ └── 小數型 (Decimal Type)
│ └── decimal (28~29 位十進位有效數字,適合金額、財務運算)
│
└── 近似值 (Approximate Numeric)
├── 浮點型 (Floating Point Types)
│ ├── float (System.Single, 32-bit, 約7位有效數字)
│ └── double (System.Double, 64-bit, 約15~16位有效數字)
|
********************************************************************************
如果需要儲存精確小數,SQL Server 欄位建議使用哪種資料型別,對應到 .NET Framework 是哪種型別 ?
ChatGPT 說:
SQL Server 儲存「精確小數」的最佳建議:
| SQL Server 型別 | 對應 .NET Framework 型別 | 特性 |
| decimal(p, s) 或 numeric(p, s) | System.Decimal | 精確小數,絕對不失真,適合金額、比例、利率等數據 |
✅ decimal 跟 numeric 在 SQL Server 是完全等價的,只是名字不同,通常大家習慣用 decimal。
SQL Server 型別 vs .NET 型別 完整對應表:
| SQL Server 型別 | .NET 型別 | 說明 |
| decimal(p,s) | System.Decimal | 高精度小數 |
| numeric(p,s) | System.Decimal | 高精度小數(跟 decimal 相同) |
(其他型別像 float、real 對應到 double、float,但那是近似,不建議用。)
********************************************************************************
(完)
相關
沒有留言:
張貼留言