【问题标题】:casting ExecuteScalar() result c#强制转换 ExecuteScalar() 结果 c#
【发布时间】:2013-03-15 15:04:46
【问题描述】:

为什么会这样

int collectionCharge = (int)cmdCheck.ExecuteScalar();

但这会产生异常

double collectionCharge = (double)cmdCheck.ExecuteScalar();

System.InvalidCastException:指定的强制转换无效。

为什么无效?

编辑 我试图简单地从查询中返回一个结果,该结果得到一些运费的价格。所以我不能把它变成int,因为它必须有小数,因此试图转换为double。我还在学习asp.net,所以如果有更好的方法来实现这一点,请指出正确的方向:)

编辑 2 完整的 SQL 代码...

using (SqlCommand cmdCheck = new SqlCommand("SELECT FREIGHT_PRICE FROM FREIGHT_QUOTER_BELNL_NEW WHERE CUSTOMER_NO = @CUSTOMER_NO AND COUNTRY = @COUNTRY AND ROUND(WEIGHT_FROM,0) < @WEIGHT AND ROUND(WEIGHT_TO,0) >= @WEIGHT AND SHIPVIA = '48';", connection))
                {
                    double collectionCharge = (double)cmdCheck.ExecuteScalar();
                    FreightAmount = collectionCharge;
                }

【问题讨论】:

  • 因为它返回一个 int,而不是返回一个 double?
  • 我不知道,但双重演员可能会让你通过这个:(double)(int)cmdCheck.ExecuteScalar()
  • @DJKRAZE,它也不会直接返回int。您的评论和投票表明您不理解他的问题。
  • @Stuart 转换是一个表达式。这就像说你知道你可以做 1+1,但不知道 (1+1)+1 也有效。
  • @DJKRAZE,很明显你有误解。 ExecuteScalar 将返回一个对象,该对象包含结果第一行第一列的值。除非您想在代码中处理对象,否则您会将结果转换为更适用的类型。将其转换为您希望使用的类型是完全有意义的。他的问题是为什么直接演员不加倍工作。 ExecuteScalar 在这里只涉及到切线。

标签: c# asp.net casting executescalar


【解决方案1】:

这里的问题是ExecuteScalar 正在返回一个int,它被装箱到object 中。要转换为double,您必须先将其拆箱为int,然后再转换为double

double collectionCharge = (double)(int)cmdCheck.ExecuteScalar();

【讨论】:

  • 如果执行返回DBNull => InvalidCastException: Specified cast is not valid. 如果返回null -> NullReferenceException: Object reference not set to an instance of an object.
【解决方案2】:

使用 Convert.ToXXX 避免无效转换异常。

I.E

collectionCharge=Convert.ToDouble(cmdCheck.ExecuteScalar());

看起来 ExecuteScalar 返回一个对象,所以代码:

double collectionCharge = (double)cmdCheck.ExecuteScalar();

还是会失败

【讨论】:

  • 很好的解决方案,特别是因为不同的数据库类型在相似的情况下返回不同的数字类型。例如,MsSql 中的 SELECT @@IDENTITY 返回十进制,而在 MsAccess-SQL 中返回一个 int。
【解决方案3】:

感谢@DJKRAZE。

我将我的查询更新为 SELECT CASE(FREIGHT_PRICE AS FLOAT),它现在可以与 (double) cast 一起使用。

double collectionCharge = (double)cmdCheck.ExecuteScalar();

【讨论】:

  • 这对异常来说是不安全的。请参阅我对 JaredPar 答案的评论。请查看此解决方案:stackoverflow.com/questions/870697/…
  • Stuart 我很抱歉没有为您提供一个确切的示例,而是以 Scope_Identity 为例为您提供了示例,从而使您找到了正确的解决方案。+1 能够根据建议
  • @asawyer,我同意你的观点,但是在我的情况下,它不会出现空值,因为我们在被查询的视图中的这个字段上有一个 NVL() 所以它永远不会为空(但是0).
【解决方案4】:

阅读所有答案后,我确实收到了十进制值,解决方案很简单! 我刚刚将函数声明为字符串,并将 Decimal 值作为字符串接收!

public static string Sals_AccountExpensesGetSums(int accountID)

{

SqlParameterHelper sph = new 
SqlParameterHelper(ConnectionString.GetWriteConnectionString(), 
"sals_AccountExpenses_GetAllSums", 1);

sph.DefineSqlParameter("@AccountID", SqlDbType.Int, ParameterDirection.Input, accountID);


string res = sph.ExecuteScalar().ToString();

return res;
}

在业务层中,我将结果更改为加倍!

public static decimal GetAccountExpensesSums(int accountId)
{
string res = "";
decimal sums = 0;

res = DBAccount.Sals_AccountExpensesGetSums(accountId);

// check so we will not have exception 
if ( res != "")
sums = Convert.ToDecimal(res);

return sums;

}

结果很完美:889678.70

【讨论】:

    【解决方案5】:

    我建议使用以下代码:

    object o = c.ExecuteScalar();
         if (o != null)
         {
             int x = Int32.Parse(o.ToString());      
         }
    

    这有两件事。首先,它确保您的 c.ExecuteScalar() 没有返回 null 如果它这样做并且您尝试强制转换,那么您会遇到问题。

    其次,它使强制转换变得更加简单,因为它可以应用于从查询中读取的几乎所有情况。

    对象变成一个字符串。如果你想要它作为一个字符串,你就完成了。 如果您希望它为布尔值,请检查该 string.Equals("true") 如果你想要它作为一个整数,Int32.Parse(string); 如果你想要它很长,Int64.Parse(string);

    基本上,您不必担心完全理解重载/显式转换。

    【讨论】:

    • 将某些内容转换为字符串,以便您可以将其转换回数字?这似乎非常笨拙和缓慢。在我看来,根据我的经验(PostgreSQL smallint 可以转换为短整数,但不能转换为整数)以及阅读此线程,其中一种 Convert 方法是最好的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2017-11-25
    • 1970-01-01
    • 1970-01-01
    • 2015-12-06
    • 2011-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多