【问题标题】:Which Data Type in C# Should I use to enter data into a Decimal Column in T-SQL?我应该使用 C# 中的哪种数据类型将数据输入到 T-SQL 中的十进制列中?
【发布时间】:2011-10-17 01:08:50
【问题描述】:

我很难弄清楚我将在 C# 中使用哪种数据类型将数据输入到我的数据库中包含小数 (5,2) 的表中。当我尝试使用 C# 十进制数据类型时,它说将数字转换为十进制时出错。当我尝试字符串时,它说它无法将 nvarchar 转换为十进制。当我尝试浮动时......同样的事情发生了,除了借口是“真正的”数据类型。 double 也失败了。

我有一个存储过程,可以将数据输入到我的表中,但是在我运行存储过程中的数据类型并将其转换为实际的十进制之前,有没有其他方法可以转换 ac# 数据类型以适应我的小数(5,2)字段?

private void btnAddClientComputer_Click(object sender, EventArgs e)
{
    SQLCommands comm = new SQLCommands();
    try
    {
        comm.AddClientComputer(int.Parse(cbCustomerID.Text), cbAction.Text, decimal.Parse(tbCost.Text));
    }
    catch (FormatException)
    {
        MessageBox.Show("The cost you have entered is invalid. Please ensure the cost is above 0, and is an actual number", "Invalid Input at Cost", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
    }
}

...

public void AddClientComputer(int CustomerID, string Action, decimal Cost)
{
    try
    {
        comm = new SqlCommand("UspAddClientComputer", conn); // Stored Procedure - see sql file
        comm.Parameters.AddWithValue("@CustomerID", CustomerID);
        comm.Parameters.AddWithValue("@Action", Action);
        comm.Parameters.AddWithValue("@Cost", Cost);
        comm.CommandType = CommandType.StoredProcedure;
        comm.ExecuteNonQuery();
    }
    catch (Exception ex)
    {
        System.Windows.Forms.MessageBox.Show(ex.Message, "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
    }
}

...

CREATE TABLE ClientComputers
            (ClientComputerID int Identity(1,1) primary key clustered
            ,CustomerID int
            ,Action varchar(7) check (Action = 'Upgrade' OR Action = 'Store')
            ,Cost decimal(5,2) check (Cost > 0)
            ,Constraint FKCustomerComputer FOREIGN KEY (CustomerID) REFERENCES Customers(CustomerID));
Go

...

CREATE PROCEDURE uspAddClientComputer @CustomerID int, @Action varchar(7), @Cost decimal(5,2)
AS
BEGIN TRY
    BEGIN TRANSACTION TrnAddClientComputer;
     INSERT INTO [TCTdb].[dbo].[ClientComputers]
           ([CustomerID]
           ,[Action]
           ,[Cost])
     VALUES
           (@CustomerID
           ,@Action
           ,@Cost)
    COMMIT TRANSACTION TrnAddClientComputer;
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION TrnAddClientComputer;

    DECLARE @ErrorMessage NVARCHAR(4000);
    DECLARE @ErrorSeverity INT;
    DECLARE @ErrorState INT;

    SELECT 
        @ErrorMessage = ERROR_MESSAGE(),
        @ErrorSeverity = ERROR_SEVERITY(),
        @ErrorState = ERROR_STATE();

    RAISERROR (@ErrorMessage,
               @ErrorSeverity,
               @ErrorState
               );
END CATCH
GO

【问题讨论】:

  • .NET 的decimal 将是合乎逻辑且最合适的选择...您能否向我们展示一些导致您遇到此错误的代码??
  • 当然。给我一点时间来编辑我的帖子
  • 您是否也在使用十进制(5,2)作为存储过程参数?
  • 好吧,在编辑我的帖子后,我明白了:D
  • 只是想知道:你有DECIMAL(5,2) - 你希望这种类型能够保持什么范围的值?您是否有可能期望小数点前 5 位和小数点后 2 位?那将是不正确 - dec(5,2) 表示:5 位 total,其中 2 位在小数点之后 - 所以你将自己限制在最大值的999.99。这到底是不是问题的核心??

标签: c# tsql types sqldatatypes


【解决方案1】:

在这种情况下,我找到了解决问题的方法,感谢 sll 引起了我的注意。以下代码对我有用。

private void btnAddClientComputer_Click(object sender, EventArgs e)
{
    SQLCommands comm = new SQLCommands();
    double trycost;
    if (double.TryParse(tbCost.Text,out trycost))
    {
        comm.AddClientComputer(int.Parse(cbCustomerID.Text), cbAction.Text, trycost);
    }
    else
    {
        MessageBox.Show("The cost you have entered is invalid. Please ensure the cost is above 0, and is an actual number", "Invalid Input at Cost", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
    }
}

...

public void AddClientComputer(int CustomerID, string Action, double Cost)
    {
        try
        {
            comm = new SqlCommand("UspAddClientComputer", conn); // Stored Procedure - see sql file
            comm.Parameters.AddWithValue("@CustomerID", CustomerID);
            comm.Parameters.AddWithValue("@Action", Action);
            comm.Parameters.Add(new SqlParameter("@Cost",Cost));
            comm.CommandType = CommandType.StoredProcedure;
            comm.ExecuteNonQuery();
        }
        catch (Exception ex)
        {
            System.Windows.Forms.MessageBox.Show(ex.Message, "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
        }
    }

..这里是解决方案部分。我用 smallmoney 替换了 Decimal(5,2)。

CREATE TABLE ClientComputers
            (ClientComputerID int Identity(1,1) primary key clustered
            ,CustomerID int
            ,Action varchar(7) check (Action = 'Upgrade' OR Action = 'Store')
            ,Cost smallmoney check (Cost > 0)
            ,Constraint FKCustomerComputer FOREIGN KEY (CustomerID) REFERENCES Customers(CustomerID));
Go

---------STORED PROCEDURES
--ADD CLIENT COMPUTER
CREATE PROCEDURE uspAddClientComputer @CustomerID int, @Action varchar(7), @Cost smallmoney
AS
BEGIN TRY
    BEGIN TRANSACTION TrnAddClientComputer;
     INSERT INTO [TCTdb].[dbo].[ClientComputers]
           ([CustomerID]
           ,[Action]
           ,[Cost])
     VALUES
           (@CustomerID
           ,@Action
           ,@Cost)
    COMMIT TRANSACTION TrnAddClientComputer;
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION TrnAddClientComputer;

    DECLARE @ErrorMessage NVARCHAR(4000);
    DECLARE @ErrorSeverity INT;
    DECLARE @ErrorState INT;

    SELECT 
        @ErrorMessage = ERROR_MESSAGE(),
        @ErrorSeverity = ERROR_SEVERITY(),
        @ErrorState = ERROR_STATE();

    RAISERROR (@ErrorMessage,
               @ErrorSeverity,
               @ErrorState
               );
END CATCH
GO

感谢所有尝试过的人。这回答了我的问题。正确的想法,错误数据类型。

【讨论】:

  • 很高兴听到你已经整理出来但仍然不清楚为什么 decimal(,) 不适合你,看看这篇文章a2zmenu.com/Blogs/Sql/Arithmetic-overflow-error.aspx
  • 这可能是一个错误吗?你的代码似乎是正确的方法(现在就像晚上 11 点,我很累,也没有集中注意力)。这可能是更深层次的东西。如果小数(5,2)太小怎么办?我用 4599.95 的值测试了它(应该和南非兰特一起工作)
  • 是的,你可以定义小数(8,3) 并试一试
  • 可能就是这样。我正在寻找存储空间。感谢您的帮助
【解决方案2】:

我建议您添加指定类型的小数参数。这意味着不仅要使用 AddWithValue,还要创建一个 Parameter 对象。

我怀疑问题是由于代码无法干净地转换而引起的。

预计到达时间:

你的代码是

comm.Parameters.Add("@Cost",SqlDbType.Decimal);
comm.Parameters["@Cost"].Value = Cost;

你需要做一些类似的事情(正如我所说,我没有容易获得的语法检查)

SqlParameter param= new SqlParameter("@Cost", SqlDbType.Decimal, Cost);//there are more parameters which I cannot remember
comm.Parameters.Add(param);

重要的是创建一个可以传入所有参数的对象,这些参数可以清楚地定义为 SQL 小数。

【讨论】:

  • 好的,我使用了一个参数对象(我认为)。我说的是 comm.Parameters.Add("@Cost",SqlDbType.Decimal);然后跟进 comm.Parameters["@Cost"].Value = Cost;给了我同样的错误
  • 您是否尝试过使用新的 SqlParameter(...) 的版本?我使用 SP + decimal(,) 使用相同的代码并且一切正常
  • 刚刚拥有。同样的错误。我要尽快尝试一下。这可能是我必须使用的错误数据类型。
  • 好的,我已经解决了我的问题,但是这个问题发生的事情离我们很远了。我现在将发布我的答案。
【解决方案3】:

试试

 comm.Parameters.Add(new SqlParameter("@Cost", Cost));

顺便说一句,

你可以重构下面的块

 try
    {
        comm.AddClientComputer(int.Parse(cbCustomerID.Text), cbAction.Text, decimal.Parse(tbCost.Text));
    }
    catch (FormatException)
    {
        MessageBox.Show("The cost you have entered is invalid. Please ensure the cost is above 0, and is an actual number", "Invalid Input at Cost", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
    }

// TODO: do the same for int.Parse as well
decimal userDefinedCost;
if (decimal.TryParse(tbCost.Text, out userDefinedCost))
{
     comm.AddClientComputer(int.Parse(cbCustomerID.Text), cbAction.Text, userDefinedCOst);
}
else
{
     MessageBox.Show("The cost you have entered is invalid. Please ensure the cost is above 0, and is an actual number", "Invalid Input at Cost", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
}

【讨论】:

  • 运气不好。上面的这段代码仍然给我同样的错误。但是确实给了我一个想法。我一开始就使用十进制,本来可以使用smallmoney。但现在这可能很有趣,想知道如何解决仍然......
  • @Eon Rusted du Plessis:如果您使用最具体的代码会怎样:SqlParameter param = new SqlParameter("@cost", SqlDbType.Decimal, 5); param.Precision = 2; - 这有什么不同吗?
  • 我可以看看它是否有效,但正如我的回答中所述,我将十进制数据类型转换为 smallmoney,因为我正在处理服务成本。十进制很好用(如果我让它工作的话),但我的直觉说 smallmoney 可能更好(money 数据类型更大,几乎没有人那么富有)
猜你喜欢
  • 2016-05-13
  • 2015-11-19
  • 2012-11-07
  • 1970-01-01
  • 1970-01-01
  • 2012-08-24
  • 1970-01-01
  • 2023-03-29
相关资源
最近更新 更多