这是一个错误还是正常:Money - SqlDataReader vs OleDbDataReader

时间:2016-07-14 23:04:49

标签: c# .net vb.net ado.net

我们最近收到的投诉是,最终数量开始显示为4位小数,如1.2300而不是1.23,使用Sql Server DB。我们的应用程序并不完美 - 到了最后它只需要调用

Convert.ToString(reader("field"))

但在我们直接使用OleDb提供商之前,几年前我们开始使用抽象提供商,幕后使用基于连接设置的SqlClientODP.NET

以下是调用Convert.ToString(reader("field"))

时发生的情况

OLEDB

  

数据库字段为十进制 - 读者数据类型为decimal,返回为1.0000
  数据库字段为资金 - 读者数据类型为decimal,返回为 1.00< -

的SqlClient

  

数据库字段为十进制 - 读者数据类型为decimal,返回为1.0000
  数据库字段为资金 - 读者数据类型为decimal,返回为 1.0000< -

应用程序是> 10yo,据我所知,整个事情投入了事实 Money 返回0.00和字段 Decimal 返回任何精度。

但我想知道这是否是某种无意的行为?除非我找到天才解决方案,否则在相当大的代码库中全局修复它可能需要付出一些显着的努力。

1 个答案:

答案 0 :(得分:0)

依赖于类型的默认格式是最好的短视,应该避免使用指定特定格式。

ToString System.Decimal方法使用其比例因子来确定小数点右侧显示的位数。可以使用重载来设置构造函数中的比例因子:Decimal Constructor (Int32, Int32, Int32, Boolean, Byte)

SQL Server money类型由.Net读取为System.Decimal。 SQLClient提供程序将类型的内部比例设置为4.在我的测试中,SQL Server Native Client中的OLE DB提供程序根据检索的值设置比例,比例范围可以从0到4。

出于本答案的目的,假设一个具有此模式的表。

CREATE TABLE [dbo].[TestSQLD_M](
    [ID] [int] NOT NULL,
    [D2] [decimal](18, 2) NULL,
    [D4] [decimal](18, 4) NULL,
    [M] [money] NULL,
 CONSTRAINT [PK_TestSQLD_M] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

D2.ToString会产生:#。##

D4.ToString会产生:#。####

M.ToString会产生:#或#。#或#。###或#。####取决于M

的值

要强制M使用默认格式#.##,您可以使用SQL decimal子句中的所需比例因子将值转换为Select。所以而不是:

Select ID, D2, D4, M From TestSQLD_M

使用:

Select ID, D2, D4, Cast(M As decimal(18,2)) As M From TestSQLD_M

这将使用SQLClientOLE DB Provider in SQL Server Native Client生成相同的格式。