使用 Decimal 参数的数据类型不匹配 - OleDb、C#、Access

Posted

技术标签:

【中文标题】使用 Decimal 参数的数据类型不匹配 - OleDb、C#、Access【英文标题】:Data type mismatch using Decimal parameter- OleDb, C#, Access 【发布时间】:2013-04-22 03:28:27 【问题描述】:

好的,所以我正在尝试将已在我的程序中更新的私有成员发送到访问数据库。但是,每当我运行程序并按下保存按钮时,我都会收到“条件表达式中的数据类型不匹配”异常。

这是我正在使用的代码 sn-p。它在 da.Update 命令中引发异常。所以我知道这与我的更新命令或我的参数有关。 由于我一直在尝试缩小问题范围,因此我还注释掉了重复的部分。

OleDbConnection conn = new OleDbConnection(ConnString);

        string sql = @" SELECT * FROM Account where AccountID = '" + accountName + @"'";

        string update = @" UPDATE Account SET
                        Cash = '@Cash'";/*, PaidInCapital = '@PaidInCapital',
                        TotalRetainedEarnings = '@TotalRetainedEarnings',
                        StockholdersEquity = '@StockholdersEquity',
                        CommonStock = '@CommonStock', PreferredStock = '@PreferredStock',
                        TreasuryStock = '@TreasuryStock', CashDividends = '@CashDividends',
                        StockDividends = '@StockDividends', @"TotalNumberPreferred = '@TotalNumberPreferred',
                        PreferredMarketPrice = '@PreferredMarketPrice', PreferredPar = '@PreferredPar',
                        Cumulative = '@Cumulative', TotalNumberCommon = '@TotalNumberCommon',
                        CommonMarketPrice = '@CommonMarketPrice', CommonPar = '@CommonPar',
                        NumberTransactTreasuryStock = '@NumberTransactTreasuryStock',
                        AvgPriceTreasury = '@AvgPriceTreasury'";*/


        try
        
            OleDbDataAdapter da = new OleDbDataAdapter();

            da.SelectCommand = new OleDbCommand(sql, conn);

            AccountDatabaseDataSet ds = new AccountDatabaseDataSet();

            da.Fill(ds, "Account");

            DataTable dt = ds.Tables["Account"];

            dt.Rows[0][1] = cash;
            /*dt.Rows[0][2] = paidInCapital;
            dt.Rows[0][3] = totalRetainedEarnings;
            dt.Rows[0][4] = stockholdersEquity;
            dt.Rows[0][5] = commonStock;
            dt.Rows[0][6] = preferredStock;
            dt.Rows[0][7] = treasuryStock;
            dt.Rows[0][8] = cashDividends;
            dt.Rows[0][9] = stockDividends;
            dt.Rows[0][10] = totalNumberPreferred;
            dt.Rows[0][11] = preferredMarketPrice;
            dt.Rows[0][12] = preferredPar;
            dt.Rows[0][13] = preferredRate;
            dt.Rows[0][14] = cumulative;
            dt.Rows[0][15] = totalNumberCommon;
            dt.Rows[0][16] = commonMarketPrice;
            dt.Rows[0][17] = commonPar;
            dt.Rows[0][18] = numberTransactTreasury;
            dt.Rows[0][19] = avgPriceTreasury;*/

            OleDbCommand cmd = new OleDbCommand(update, conn);

            cmd.Parameters.Add("@Cash", OleDbType.Decimal, 18, "Cash");
            /*cmd.Parameters.Add("@PaidInCapital", OleDbType.Decimal, 18, "PaidInCapital");
            cmd.Parameters.Add("@TotalRetainedEarnings", OleDbType.Decimal, 18, "TotalRetainedEarnings");
            cmd.Parameters.Add("@StockholdersEquity", OleDbType.Decimal, 18, "StockholdersEquity");
            cmd.Parameters.Add("@CommonStock", OleDbType.Decimal, 18, "CommonStock");
            cmd.Parameters.Add("@PreferredStock", OleDbType.Decimal, 18, "PreferredStock");
            cmd.Parameters.Add("@TreasuryStock", OleDbType.Decimal, 18, "TreasuryStock");
            cmd.Parameters.Add("@CashDividends", OleDbType.Decimal, 18, "CashDividends");
            cmd.Parameters.Add("@StockDividends", OleDbType.Decimal, 18, "StockDividends");
            cmd.Parameters.Add("@TotalNumberPreferred", OleDbType.Integer, 16, "TotalNumberPreferred");
            cmd.Parameters.Add("@PreferredMarketPrice", OleDbType.Decimal, 10, "PreferredMarketPrice");
            cmd.Parameters.Add("@PreferredPar", OleDbType.Decimal, 10, "PreferredPar");
            cmd.Parameters.Add("@PreferredRate", OleDbType.Decimal, 5, "PreferredRate");
            cmd.Parameters.Add("@Cumulative", OleDbType.Boolean, 2, "Cumulative");
            cmd.Parameters.Add("@TotalNumberCommon", OleDbType.Integer, 16, "TotalNumberCommon");
            cmd.Parameters.Add("@CommonMarketPrice", OleDbType.Decimal, 10, "CommonMarketPrice");
            cmd.Parameters.Add("@CommonPar", OleDbType.Decimal, 10, "CommonPar");
            cmd.Parameters.Add("@NumberTransactTreasuryStock", OleDbType.Integer, 16, "NumberTransactTreasuryStock");
            cmd.Parameters.Add("@AvgPriceTreasury", OleDbType.Decimal, 10, "AvgPriceTreasury");*/


            da.UpdateCommand = cmd;
            da.Update(ds, "Account");

如果你去掉注释部分,基本上可以缩小到这个范围:

OleDbConnection conn = new OleDbConnection(ConnString);

        string sql = @" SELECT * FROM Account where AccountID = '" + accountName + @"'";

        string update = @" UPDATE Account SET
                        Cash = '@Cash'";
        try
            OleDbDataAdapter da = new OleDbDataAdapter();

            da.SelectCommand = new OleDbCommand(sql, conn);

            AccountDatabaseDataSet ds = new AccountDatabaseDataSet();

            da.Fill(ds, "Account");

            DataTable dt = ds.Tables["Account"];

            dt.Rows[0][1] = cash;

            OleDbCommand cmd = new OleDbCommand(update, conn);

            cmd.Parameters.Add("@Cash", OleDbType.Decimal, 18, "Cash");

            da.UpdateCommand = cmd;
            da.Update(ds, "Account");
         

所以,基本上我有一个“帐户”表,我想将第二个 [1] 列设置为等于十进制类型的私有成员变量“现金”。然后我为“@Cash”参数设置我的参数,其中 OleDbType 是十进制,大小是 18,访问数据库中的列是“现金”。最后我用这个值更新了“Account”表。

现在我尝试将我的 oledbtype 中的 .Decimal 更改为列表中的所有可能类型,但它似乎永远不会起作用,甚至一些异常将其声明为“无法转换为 DateTime 的十进制类型”,例如。所以我被引导相信 oledbtype 不是问题。我也尝试过弄乱参数中的大小,但这也没有奏效。

我已尽力解释这一点,但如果还有其他有助于解决此问题的内容,我会提供。

【问题讨论】:

为什么人们会给OleDbParameters 起名字? msdn.microsoft.com/en-AU/library/… 当 CommandType 设置为 Text 时,OLE DB .NET 提供程序不支持将参数传递给 SQL 语句或由 OleDbCommand 调用的存储过程的命名参数。在这种情况下,必须使用问号 (?) 占位符。 但是不管文档应该怎么做,UPDATE Account SET Cash = '@Cash' 是错误的:你不需要在参数占位符周围加上' @ta.speot.is 显然它可能,我只是像你在第二条评论中所说的那样取出了“'”,在更新中添加了 where 子句,我能够得到它去工作。虽然它很冗长,但我相信它应该发挥作用。 【参考方案1】:

这是解决我更新问题的代码,以供将来需要帮助的人参考。这是在 Visual Studio 2012 中使用 MS Access 的数据集:

public void UpdateValues(string accountName)
    
        OleDbConnection conn = new OleDbConnection(ConnString);

        string sql = @" SELECT * FROM Account where AccountID = '" + accountName + @"'";

        string update = "UPDATE Account SET Cash = ?, PaidInCapital = ?, TotalRetainedEarnings = ?, StockholdersEquity = ?, " +
                        "CommonStock = ?, PreferredStock = ?, TreasuryStock = ?, CashDividends = ?, StockDividends = ?, " +
                        "TotalNumberPreferred = ?, PreferredMarketPrice = ?, PreferredPar = ?, Cumulative = ?, TotalNumberCommon = ?, " +
                        "CommonMarketPrice = ?, CommonPar = ?, NumberTransactTreasuryStock = ?, AvgPriceTreasury = ? WHERE AccountID = '" + accountName + "'";
        try
        
            OleDbDataAdapter da = new OleDbDataAdapter();

            da.SelectCommand = new OleDbCommand(sql, conn);

            AccountDatabaseDataSet ds = new AccountDatabaseDataSet();

            da.Fill(ds, "Account");

            DataTable dt = ds.Tables["Account"];

            dt.Rows[0][1] = cash;
            dt.Rows[0][2] = paidInCapital;
            dt.Rows[0][3] = totalRetainedEarnings;
            dt.Rows[0][4] = stockholdersEquity;
            dt.Rows[0][5] = commonStock;
            dt.Rows[0][6] = preferredStock;
            dt.Rows[0][7] = treasuryStock;
            dt.Rows[0][8] = cashDividends;
            dt.Rows[0][9] = stockDividends;
            dt.Rows[0][10] = totalNumberPreferred;
            dt.Rows[0][11] = preferredMarketPrice;
            dt.Rows[0][12] = preferredPar;
            dt.Rows[0][13] = preferredRate;
            dt.Rows[0][14] = cumulative;
            dt.Rows[0][15] = totalNumberCommon;
            dt.Rows[0][16] = commonMarketPrice;
            dt.Rows[0][17] = commonPar;
            dt.Rows[0][18] = numberTransactTreasury;
            dt.Rows[0][19] = avgPriceTreasury;

            OleDbCommand cmd = new OleDbCommand(update, conn);

            cmd.Parameters.Add("@Cash", OleDbType.Decimal, 18, "Cash");
            cmd.Parameters.Add("@PaidInCapital", OleDbType.Decimal, 18, "PaidInCapital");
            cmd.Parameters.Add("@TotalRetainedEarnings", OleDbType.Decimal, 18, "TotalRetainedEarnings");
            cmd.Parameters.Add("@StockholdersEquity", OleDbType.Decimal, 18, "StockholdersEquity");
            cmd.Parameters.Add("@CommonStock", OleDbType.Decimal, 18, "CommonStock");
            cmd.Parameters.Add("@PreferredStock", OleDbType.Decimal, 18, "PreferredStock");
            cmd.Parameters.Add("@TreasuryStock", OleDbType.Decimal, 18, "TreasuryStock");
            cmd.Parameters.Add("@CashDividends", OleDbType.Decimal, 18, "CashDividends");
            cmd.Parameters.Add("@StockDividends", OleDbType.Decimal, 18, "StockDividends");
            cmd.Parameters.Add("@TotalNumberPreferred", OleDbType.Integer, 16, "TotalNumberPreferred");
            cmd.Parameters.Add("@PreferredMarketPrice", OleDbType.Decimal, 10, "PreferredMarketPrice");
            cmd.Parameters.Add("@PreferredPar", OleDbType.Decimal, 10, "PreferredPar");
            cmd.Parameters.Add("@PreferredRate", OleDbType.Decimal, 5, "PreferredRate");
            cmd.Parameters.Add("@Cumulative", OleDbType.Boolean, 2, "Cumulative");
            cmd.Parameters.Add("@TotalNumberCommon", OleDbType.Integer, 16, "TotalNumberCommon");
            cmd.Parameters.Add("@CommonMarketPrice", OleDbType.Decimal, 10, "CommonMarketPrice");
            cmd.Parameters.Add("@CommonPar", OleDbType.Decimal, 10, "CommonPar");
            cmd.Parameters.Add("@NumberTransactTreasuryStock", OleDbType.Integer, 16, "NumberTransactTreasuryStock");
            cmd.Parameters.Add("@AvgPriceTreasury", OleDbType.Decimal, 10, "AvgPriceTreasury");

            da.UpdateCommand = cmd;
            da.Update(ds, "Account");
        
        catch (Exception ex)
        
            MessageBox.Show(ex.Message + ex.StackTrace, "Exception Details");
        
        finally
        
            conn.Close();
        
    

【讨论】:

【参考方案2】:

你说它正在抛出异常。您是否尝试过捕获异常并更详细地检查它?有时异常会有一个 InnerException 属性,该属性可以包含复杂对象(如 OleDb)引发的错误的更多详细信息。

【讨论】:

是的,说明如下:条件表达式中的数据类型不匹配。在 System.Data.Common.DbDataAdapter.UpdatedRowStatusErrors(RowUpda tedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, Inter32 commandCount) 等处。【参考方案3】:

如果您需要更新数据库中的行,请尝试以下操作

using (OleDbConnection conn = new OleDbConnection(ConnString))
 
       conn.Open();
       using (var cmd = conn.CreateCommand())
       
            cmd.CommandText = "UPDATE Account SET Cash=? WHERE AccountID =?";
            cmd.Parameters.Add("@p1", OleDbType.Decimal).Value = 3.1416;
            cmd.Parameters.Add("@p2", OleDbType.Integer).Value = accountName;
            cmd.ExecuteNonQuery();
       
 
使用参数,否则您的查询会因 sql 注入攻击而打开 OLE DB.NET Framework 数据提供程序使用标有问号 (?) 的位置参数,而不是命名参数。

【讨论】:

OLE DB.NET Framework 数据提供程序使用标有问号 (?) 的位置参数,而不是命名参数。 但您仍然可以命名。 Look at the example, just .Add the values。另外,OleDbCommand is IDisposable 所以在这里考虑using 声明。 @ta.speot. 是使用块添加的,但我们可以在声明时命名参数。 please check examples on MSDN @Damith 好的,所以我进行了更改,现在我的代码如下所示: using (OleDbConnection conn = new OleDbConnection(ConnString)) try conn.Open();使用 (var cmd = conn.CreateCommand()) cmd.CommandText = "更新账户设置现金 = ?, PaidInCapital = ?, WHERE AccountID = ?"; cmd.Parameters.Add("@Cash", OleDbType.Decimal).Value = cash; cmd.Parameters.Add("@PaidInCapital", OleDbType.Decimal).Value =paidInCapital; cmd.Parameters.Add("@AccountId", OleDbType.VarChar).Value = accountName; cmd.ExecuteNonQuery(); 但它仍然没有更新数据库中的任何内容 有什么例外吗?您将访问文件放在解决方案中的什么位置? @Damith None,访问文件与我的源代码位于同一文件夹中。而且我知道我可以访问数据库,因为我在一开始就填充了一个列表。

以上是关于使用 Decimal 参数的数据类型不匹配 - OleDb、C#、Access的主要内容,如果未能解决你的问题,请参考以下文章

ASP中使用MSSQL数据库,要更新的数据类型是Decimal,传入的数据类型是Int,请问大神

EF6.0 下sql语句自动生成的参数类型decimal(18,2)修改

SqlServer中decimal,float 和 real 数据类型的区别

关于decimal类型计算的问题

mysqldecimal数据类型

oracle 里的字段类型是 Number ,SQL里对应的字段是decimal