-
Notifications
You must be signed in to change notification settings - Fork 317
Description
When using SqlBulkCopy
in .NET 8 to insert decimal values into a SQL Server table, fractional parts are slightly truncated or rounded incorrectly during transfer.
Reproduction
using System;
using System.Data;
using Microsoft.Data.SqlClient;
var dataTable = new DataTable();
dataTable.Columns.Add("Amount", typeof(decimal));
dataTable.Rows.Add(33.33m);
using var connection = new SqlConnection("Data Source=.;Initial Catalog=TestDb;Integrated Security=True;");
connection.Open();
// Destination table: CREATE TABLE dbo.AmountTest (Amount DECIMAL(10,2));
using var bulkCopy = new SqlBulkCopy(connection);
bulkCopy.DestinationTableName = "dbo.AmountTest";
bulkCopy.WriteToServer(dataTable);
Actual behavior:
In the database table, the stored value is 33.32 instead of 33.33.
Expected behavior:
The destination table should contain the same value (33.33) without any loss of precision.
.NET SDK: 8.4.1425.42110
OS: Windows 11 24H2 x64
Additional context
- The issue appears related to SqlBulkCopy’s binary streaming mode introduced in .NET Core.
- Precision loss seems to happen during binary serialization of decimal values before sending to SQL Server.
- Regular INSERT commands with parameters preserve the correct precision.
- The same code using System.Data.SqlClient in .NET Framework 4.8 does not exhibit this behavior.
Additional Technical Note
This precision loss is not reproducible for all fractional numbers.
It occurs specifically for decimal values whose fractional part cannot be represented exactly in binary form — i.e., when the denominator of the fractional component is not a power of 2.
For example:
33.25 = 33 + 1/4 → exact in binary ✅
33.33 ≈ 33 + 33/100 → cannot be represented exactly in binary ❌ → results in truncation (e.g., 33.3299999237…)
During SqlBulkCopy’s binary streaming, these repeating binary fractions are rounded or truncated, leading to small losses (like 33.33 → 33.32).
This is a fundamental binary representation limitation, but previous implementations (e.g., .NET Framework’s SqlBulkCopy) handled it by scaling correctly according to the target column’s precision/scale before serialization.
Impact
Financial applications relying on decimal accuracy (e.g., currency or unit prices) experience subtle but critical rounding errors.