.NET 保存到数据库会截断我的小数而不是四舍五入。可能会出现什么问题?
.NET saving to DB truncates my decimals instead of rounds them.. what could be possible problems?
我没有使用 entity framework,但我使用的是 Microsoft Enterprise Library。
我有一个像这样的值:1.125979843654984
被截断为 1.125
,而不是四舍五入为 1.126
。
该值所在列的精度为 Decimal(5,3)。
发生这种情况的原因有哪些?
我可以提供任何其他信息来帮助您吗?
我是 .NET 新手。
更新 1
- 添加相关代码
调用保存过程的代码:
Dim dsCalcGroupByBand As New DataSet
dsCalcGroupByBand.Tables.Add(dtCalcGroupByBand)
dsCalcGroupByBand.Tables(0).TableName = "Table"
Dal.SaveGridDataSet(dsCalcGroupByBand, "Select * from tblLTDCalcGroupByBand where iGroupKY=" & GroupData.GroupNo, False, False)
变量中的method方法Dal
:
Public Function SaveGridDataSet(ByVal pDS As DataSet, ByVal pSQL As String, _
Optional ByVal pCheckIsNewGroup As Boolean = True, _
Optional ByVal pForceAsNewGroup As Boolean = False, _
Optional ByVal pSQLDelete As String = "") As Boolean
Dim DA As New SqlDataAdapter
Dim commandBuilder As SqlCommandBuilder
Dim adapter As SqlDataAdapter
Dim updatedRows As Integer
Using connection As SqlConnection = _database.CreateConnection()
Try
If ((pCheckIsNewGroup = True) And (GroupData.isNewGroup = True)) Or _
(pForceAsNewGroup = True) Then
pDS = IsNewGroup(pDS)
End If
DA = New SqlDataAdapter(pSQL, connection) '_database.GetDataAdapter
' Make the CommandBuilder generate the insert, update, and delete commands.
commandBuilder = New SqlCommandBuilder(DA)
' Save the changes.
DA.Update(pDS)
Catch e As InvalidOperationException
Try
' it's horrible to run code, in here, but there need to be tests
' implemented before modifying the above code.
adapter = New SqlDataAdapter(pSQL, connection)
commandBuilder = New SqlCommandBuilder(adapter)
'adapter.SelectCommand = commandBuilder.GetUpdateCommand
updatedRows = adapter.Update(pDS)
Catch ee As DBConcurrencyException
' there was no change (data already exists, no need to update)
Console.WriteLine("no data written")
End Try
Catch e As DBConcurrencyException
' Delete the current records using the optional delete pSQLDelete
If pSQLDelete = "" Then
pSQLDelete = pSQL.Replace("Select *", "Delete")
End If
UpdateSQL(pSQLDelete)
' Now Create the dataset as if a new group and try the update again
DA.Update(IsNewGroup(pDS))
Catch e As Exception
Console.WriteLine("Un-mitigated exception")
Console.WriteLine(e.Message)
End Try
End Using
End Function
- 对上述代码片段的免责声明:它们都来自遗留代码。
以上面的小数为例:
在 dtCalcGroupByBand
DataTable
中,存在一行值 1.125979843654984
的字段对应于数据库中数据类型为 Decimal(5,3) 的列——但是,特定的对应 DataColumn 对象是数据类型 System.Decimal
- 这可能是问题的来源?也许?
无论如何,一旦保存,(在调用 Dal.SaveGridDataSet(...)
之后),我在 table 中查找值,它显示 1.125
(截断)而不是 1.126
(四舍五入)
更新 2
使用 Microsoft Enterprise Library(或其他访问数据库的 OO 方式),如何检索列的精度?
该列声明为 Decimal(5,3),因此您将在小数值右侧获得 3 位精度,其余部分将被截断。
如果要对值进行舍入,则必须在将其保存到数据库之前在数据表列中round,或者在正在执行的SQL 语句中对其进行舍入。
我解决了在应用程序启动时加载整个架构,然后根据需要从架构中引用列信息的问题。
希望其他人不必像我一样搜索解决这个问题。
设置
' in whatever class you do your database communication:
Private _database As SqlDatabase
Private Shared _schema As DataTable
Sub New()
' or however you handle the connection string / database creation
Dim connectionString as String = GetConnectionString()
_database = New SqlDatabase(connectionString)
RetrieveSchema()
End Sub
Private Function RetrieveSchema() as DataTable
If _schema Is Nothing Then
Using connection As SqlConnection = _database.CreateConnection()
connection.Open()
_schema = connection.GetSchema("Columns")
End Using
End If
return _schema
End Function
Public Function GetColumnInformation(tableName As String, columnName As String) as DataRow
Dim firstMatchingRow as DataRow = (
From row In _schema.Rows _
Where (
row("TABLE_NAME") = tableName AndAlso row("COLUMN_NAME") = columnName)
)).FirstOrDefault()
Return firstMatchingRow
End Function
用法
Dim columnInformation As DataRow = Dal.GetColumnInformation(tableName, columnName)
' find the precision
Dim precision = columnInformation("NUMERIC_PRECISION")
Dim scale = columnInformation("NUMERIC_SCALE")
' convert the decimal to the column's format
' e.g.: 2.345 with a scale of 2 would result in
' 2.35
value = Decimal.Round(value, scale)
我没有使用 entity framework,但我使用的是 Microsoft Enterprise Library。
我有一个像这样的值:1.125979843654984
被截断为 1.125
,而不是四舍五入为 1.126
。
该值所在列的精度为 Decimal(5,3)。
发生这种情况的原因有哪些?
我可以提供任何其他信息来帮助您吗?
我是 .NET 新手。
更新 1
- 添加相关代码
调用保存过程的代码:
Dim dsCalcGroupByBand As New DataSet
dsCalcGroupByBand.Tables.Add(dtCalcGroupByBand)
dsCalcGroupByBand.Tables(0).TableName = "Table"
Dal.SaveGridDataSet(dsCalcGroupByBand, "Select * from tblLTDCalcGroupByBand where iGroupKY=" & GroupData.GroupNo, False, False)
变量中的method方法Dal
:
Public Function SaveGridDataSet(ByVal pDS As DataSet, ByVal pSQL As String, _
Optional ByVal pCheckIsNewGroup As Boolean = True, _
Optional ByVal pForceAsNewGroup As Boolean = False, _
Optional ByVal pSQLDelete As String = "") As Boolean
Dim DA As New SqlDataAdapter
Dim commandBuilder As SqlCommandBuilder
Dim adapter As SqlDataAdapter
Dim updatedRows As Integer
Using connection As SqlConnection = _database.CreateConnection()
Try
If ((pCheckIsNewGroup = True) And (GroupData.isNewGroup = True)) Or _
(pForceAsNewGroup = True) Then
pDS = IsNewGroup(pDS)
End If
DA = New SqlDataAdapter(pSQL, connection) '_database.GetDataAdapter
' Make the CommandBuilder generate the insert, update, and delete commands.
commandBuilder = New SqlCommandBuilder(DA)
' Save the changes.
DA.Update(pDS)
Catch e As InvalidOperationException
Try
' it's horrible to run code, in here, but there need to be tests
' implemented before modifying the above code.
adapter = New SqlDataAdapter(pSQL, connection)
commandBuilder = New SqlCommandBuilder(adapter)
'adapter.SelectCommand = commandBuilder.GetUpdateCommand
updatedRows = adapter.Update(pDS)
Catch ee As DBConcurrencyException
' there was no change (data already exists, no need to update)
Console.WriteLine("no data written")
End Try
Catch e As DBConcurrencyException
' Delete the current records using the optional delete pSQLDelete
If pSQLDelete = "" Then
pSQLDelete = pSQL.Replace("Select *", "Delete")
End If
UpdateSQL(pSQLDelete)
' Now Create the dataset as if a new group and try the update again
DA.Update(IsNewGroup(pDS))
Catch e As Exception
Console.WriteLine("Un-mitigated exception")
Console.WriteLine(e.Message)
End Try
End Using
End Function
- 对上述代码片段的免责声明:它们都来自遗留代码。
以上面的小数为例:
在 dtCalcGroupByBand
DataTable
中,存在一行值 1.125979843654984
的字段对应于数据库中数据类型为 Decimal(5,3) 的列——但是,特定的对应 DataColumn 对象是数据类型 System.Decimal
- 这可能是问题的来源?也许?
无论如何,一旦保存,(在调用 Dal.SaveGridDataSet(...)
之后),我在 table 中查找值,它显示 1.125
(截断)而不是 1.126
(四舍五入)
更新 2
使用 Microsoft Enterprise Library(或其他访问数据库的 OO 方式),如何检索列的精度?
该列声明为 Decimal(5,3),因此您将在小数值右侧获得 3 位精度,其余部分将被截断。
如果要对值进行舍入,则必须在将其保存到数据库之前在数据表列中round,或者在正在执行的SQL 语句中对其进行舍入。
我解决了在应用程序启动时加载整个架构,然后根据需要从架构中引用列信息的问题。
希望其他人不必像我一样搜索解决这个问题。
设置
' in whatever class you do your database communication:
Private _database As SqlDatabase
Private Shared _schema As DataTable
Sub New()
' or however you handle the connection string / database creation
Dim connectionString as String = GetConnectionString()
_database = New SqlDatabase(connectionString)
RetrieveSchema()
End Sub
Private Function RetrieveSchema() as DataTable
If _schema Is Nothing Then
Using connection As SqlConnection = _database.CreateConnection()
connection.Open()
_schema = connection.GetSchema("Columns")
End Using
End If
return _schema
End Function
Public Function GetColumnInformation(tableName As String, columnName As String) as DataRow
Dim firstMatchingRow as DataRow = (
From row In _schema.Rows _
Where (
row("TABLE_NAME") = tableName AndAlso row("COLUMN_NAME") = columnName)
)).FirstOrDefault()
Return firstMatchingRow
End Function
用法
Dim columnInformation As DataRow = Dal.GetColumnInformation(tableName, columnName)
' find the precision
Dim precision = columnInformation("NUMERIC_PRECISION")
Dim scale = columnInformation("NUMERIC_SCALE")
' convert the decimal to the column's format
' e.g.: 2.345 with a scale of 2 would result in
' 2.35
value = Decimal.Round(value, scale)