当更新Datatable时,DataRow会将十进制数的小数部分清零。

12

我想在绑定到Gridview之前,更新从数据库中检索的DataTable。

然而,当我更新十进制字段时,小数点后面的部分被设置为零。我错过了什么?

if (HttpContext.Current.Request.IsAuthenticated)
{
    // Get additional price matches
    using (SqlConnection stockConn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ConnectionString))
    {
        // Check for trade match offer
        SqlCommand tradePCCheck = new SqlCommand("getAllMyPriceMatches", stockConn);
        tradePCCheck.CommandType = CommandType.StoredProcedure;
        SqlParameter email = tradePCCheck.Parameters.Add("@email", SqlDbType.NVarChar);
        try
        {
            email.Value = this.Context.User.Identity.Name;
        }
        catch
        {
            email.Value = " ";
        }
        SqlParameter thedate = tradePCCheck.Parameters.Add("@theDate", SqlDbType.DateTime);
        thedate.Value = DateTime.Now.AddHours(-50);

        stockConn.Open();
        SqlDataReader pcReader = tradePCCheck.ExecuteReader();
        pms.Load(pcReader);
        pcReader.Close();
        stockConn.Close();
    }
}

//Set Connection, Open the DB & Fill Data Set

using (SqlConnection stockConn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ConnectionString))
{
    SqlCommand stockCommand = new SqlCommand("getTISearchResults", stockConn);
    stockCommand.CommandType = CommandType.StoredProcedure;
    SqlParameter keyword = stockCommand.Parameters.Add("@keyword", SqlDbType.NVarChar);
    keyword.Value = prefixText;
    stockConn.Open();
    SqlDataReader rd = stockCommand.ExecuteReader();
    searchResults.Load(rd);
    stockCommand.Dispose();
    rd.Dispose();
}

// Update Results with elevated prices...
foreach (DataRow dr in searchResults.Rows)
{
    // Check for PMS
    DataRow[] thePMS = pms.Select("tpc_stockid = '" + dr["stockitem_number"].ToString() + "'");

    if (thePMS.Length > 0)
    {
        decimal px = 0;
        decimal cash = 0;

        if (thePMS[0]["tpc_pricepx"] != null && !thePMS[0]["tpc_pricepx"].ToString().Equals(""))
        {
            px = Convert.ToDecimal(thePMS[0]["tpc_pricepx"]);
        }

        if (thePMS[0]["tpc_price"] != null && !thePMS[0]["tpc_price"].ToString().Equals(""))
        {
            cash = Convert.ToDecimal(thePMS[0]["tpc_price"]);
        }
        // update table and accept changes
        DataRow[] theRows = searchResults.Select("stockitem_number = '" + dr["stockitem_number"].ToString() + "' ");

        if (theRows.Length > 0)
        {
            theRows[0]["stockitem_pxprice"] = px;
            theRows[0]["stockitem_cashprice"] = cash;
            searchResults.AcceptChanges();
        }
    }
}

gvSearchResults.DataSource = searchResults;
gvSearchResults.DataBind();

在分配之前,我已经输出了PX和现金,并且它们持有正确的值800.19和500.12,但是在AcceptChanges之后并绑定后,输出为800.00和500.12。

theRows[0]["stockitem_pxprice"]theRows[0]["stockitem_cashprice"]都是从填充搜索结果的数据库上的decimal(5,2)类型。

非常感谢您的任何帮助。

谢谢。


2
Convert.ToDecimal() 调用之后,pxcash 的中间值是什么?我会考虑这里可能存在文化问题,但一个能正常工作而另一个不能似乎非常奇怪。 - user
3
您是否在从SqlReader加载searchResults之前声明了其结构(架构)(schema)?也许您的stockitem_pxprice被声明为typeof(int) - Alex Filipovici
检查datatable searchResults的声明/定义。可能存在一些类型不匹配。 - gee'K'iran
搜索结果字段被声明为decimal(5,2),在计算之前,px和cash都有正确的小数位。 - Ben Drury
searchResults 变量在哪里声明的?它是如何创建的? - Ann L.
@BenDrury 请确保您要更新的表格不包含任何类型的TRIGGER(T-SQL TRIGGERS),且此触发器不会将十进制值进行四舍五入或截断。 - Jesse
4个回答

2

在设置网格的值时,您需要使用string.format格式化双精度浮点数。否则会出现问题。

例如,如果您有一个数字4.506,它将显示为4.5060,如果您有一个数字4.5,则会显示为4.50。

我曾在模板化的网格视图中遇到此问题,并不得不使用字符串格式和格式说明符来解决它。


0

我不确定你是否已经得到答案,但我想分享一下,我通过使用 SqlDataReader 的方法来解决了这个问题,它是 GetDecimal 方法。你可以编写如下代码

using (SqlConnection stockConn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ConnectionString))
{
        // Check for trade match offer
        SqlCommand tradePCCheck = new SqlCommand("getAllMyPriceMatches", stockConn);
        tradePCCheck.CommandType = CommandType.StoredProcedure;
        SqlParameter email = tradePCCheck.Parameters.Add("@email", SqlDbType.NVarChar);
        try
        {
            email.Value = this.Context.User.Identity.Name;
        }
        catch
        {
            email.Value = " ";
        }
        SqlParameter thedate = tradePCCheck.Parameters.Add("@theDate", SqlDbType.DateTime);
        thedate.Value = DateTime.Now.AddHours(-50);

        stockConn.Open();

    SqlDataReader pcReader = tradePCCheck.ExecuteReader();

    decimal px = 0;
    decimal cash = 0;

    if (pcReader.Read())
    {
        px = pcReader.GetDecimal(0);
        cash = pcReader.GetDecimal(1);
    }
    pcReader.Close();
    stockConn.Close();
}

pcReader.GetDecimal(0) 的意思是从结果集中以十进制数值获取索引为 0 的数据字段,它是 SELECT 命令中所选列的顺序。 而存储过程 getAllMyPriceMatches,您可以使用 JOIN 命令在两个表结果之间修改查询脚本,然后您就不需要第二个查询范围了。


0

我认为你的表格有以下两个字段是 int 数据类型:

  • stockitem_pxprice

  • stockitem_cashprice

请将这两个字段的数据类型修改为 numeric (18,2) 或者 [decimal](18, 2)

无需进行类型转换,asp.net 会自动隐式转换。


表格中的字段是十进制数(5,2)。 - Ben Drury

0
遍历theRows.Columns并转储.Type属性以进行跟踪。您已经多次提到类型是decimal(5,2),这是TSQL类型。DataTable保存c#类型,即十进制数,类似于非常大的浮点数。这里重要的是c#类型。
在您的tsql中可能会有一些转换,例如Select myVal * 1将您的myVal十进制数转换为整数。然后,这将是您的datatable所持有的类型。我通常将我的常量设置为myVal *1.0之类的东西,以防止值变成整数。就像您必须在c#中声明一个十进制数,如100m,在TSQL中,您必须确保文字常量被特别声明以防止数据类型转换。
参考http://msdn.microsoft.com/en-us/library/ms179899.aspx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接