C# 我应该在这里投什么类型?

C# What type should I cast here?

我有一部分代码通过从数据库中读取所有先前的费用和付款来计算新的余额,然后将要记入余额的新金额相加。它可以很好地处理我手动输入数据库的值,但是当我擦除所有测试值并从头开始时我开始出错。

这是代码:

        //sum all prior charges
        try
        {
            connection.Open();
            command.Connection = connection;

            command.CommandText = "SELECT SUM(Amount) FROM Charges WHERE TransactionDate<='" + DateTime.Now + "';";
            chargesSoFar = (double)command.ExecuteScalar();
            connection.Close();
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error: " + ex.Message);
        }

        // sum all prior payments
        try
        {
            connection.Open();
            command.Connection = connection;

            command.CommandText = "SELECT SUM(Amount) FROM Payments WHERE TransactionDate<='" + DateTime.Now + "';";
            paymentsSoFar = (double)command.ExecuteScalar();
            connection.Close();
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error: " + ex.Message);
        }

        // calculate balance
        tempCharge.Balance = (decimal)(chargesSoFar + int.Parse(textBoxAmount.Text) - paymentsSoFar);

        DataWriter.WriteCharge(tempCharge);

我遇到的错误是我转换 ExecuteScalar 结果的类型转换错误。发生错误是因为没有先前的费用或付款,因此返回 null,在转换为 double 时失败。

是否可以转换为另一种类型,然后我可以检查它是否为空?如果没有,我该如何解决这个问题?

感谢任何帮助。如果我不清楚我在这里要做什么,请提出任何问题。

您可以使用问号后缀转换为可空类型,即 (double?),然后检查是否为空。

     paymentsSoFar = (double?)command.ExecuteScalar()
     if (paymentSoFar.HasValue){

同时阅读 SQL 注入:https://www.acunetix.com/websitesecurity/sql-injection/ 因为您的代码目前容易受到此类攻击

尝试可为空的数据类型:

double? chargesSoFar = null;
// other codes here
chargesSoFar = (double?)command.ExecuteScalar();

作为旁注,参数化查询很可能是防止 sql 注入的最佳实践。为此,

try
{
    connection.Open();
    command.Connection = connection;

    command.CommandText = "SELECT SUM(Amount) FROM Payments WHERE TransactionDate <= @TransData;";
    command.Parameter.AddWithValue("TransData", DateTime.Now);
    chargesSoFar = (double?)command.ExecuteScalar();
    connection.Close();
}
catch (Exception ex)
{
    MessageBox.Show("Error: " + ex.Message);
}

根据这个问题:What is the best data type to use for money in c#?

最好使用的数据类型是十进制。

decimal? chargesSoFar = null;
// other codes here
chargesSoFar = (decimal?)command.ExecuteScalar();

也许你可以转换为 Nullable<double>double?

double? paymentsSoFar = (double?)command.ExecuteScalar();

if(paymentsSoFar.HasValue)
{
    // Then its safe to calculate 

    double myActualValue = paymentsSoFar.Value;
}

Nullable Types (C# Programming Guide)

Nullable types have the following characteristics:

  • Nullable types represent value-type variables that can be assigned the value of null. You cannot create a nullable type based on a reference type.

  • The syntax T? is shorthand for Nullable<T>, where T is a value type. The two forms are interchangeable.

  • Assign a value to a nullable type just as you would for an ordinary value type, for example int? x = 10; or double? d = 4.108. A nullable type can also be assigned the value null: int? x = null.

  • Use the Nullable<T>.GetValueOrDefault method to return either the assigned value, or the default value for the underlying type if the value is null, for example int j = x.GetValueOrDefault();

  • Use the HasValue and Value read-only properties to test for null and retrieve the value, as shown in the following example: if(x.HasValue) j = x.Value;

  • The HasValue property returns true if the variable contains a value, or false if it is null.

  • The Value property returns a value if one is assigned. Otherwise, a System.InvalidOperationException is thrown.

  • The default value for HasValue is false. The Value property has no default value.

  • You can also use the == and != operators with a nullable type, as shown in the following example: if (x != null) y = x;

  • Use the ?? operator to assign a default value that will be applied when a nullable type whose current value is null is assigned to a non-nullable type, for example int? x = null; int y = x ?? -1;

  • Nested nullable types are not allowed. The following line will not compile: Nullable<Nullable<int>> n;