【问题标题】:Specified cast is not valid - System.InvalidCastException指定的强制转换无效 - System.InvalidCastException
【发布时间】:2016-04-07 22:34:32
【问题描述】:

我已经阅读了许多类似的问题并尝试了几种不同的方法,但我不明白为什么这不起作用。求和的列是 int 类型。我尝试过转换为 uint 和 int32。我很欣赏方向。谢谢你。

        int i = 1;
        int total=0;
        while (i < 7)
        {

            string conString = @"Data Source=UATDB2\sqleuat;Initial Catalog=CVNee;User ID=appuser;Integrated Security=true";

            SqlConnection connection = new SqlConnection(conString);
            connection.Open();
            SqlCommand cmd = connection.CreateCommand();
            cmd.CommandText = "SELECT SUM(AMOUNT) FROM TRANSACTIONS_DETAIL2 WHERE TRANSACTIONS_DETAIL2.TRANS_TYPE =" + i + "AND TRANSACTIONS_DETAIL2.HOH_UPI = '185292000'";

           int amt = ((int)cmd.ExecuteScalar());
            //amt = cmd.ExecuteScalar();

            if (i == 1)
            {
                total = total + amt;
            }

            if (i == 2)
            {
                total = total - amt;
            }

            if (i == 3)
            {
                total = total - amt;
            }

            if (i == 4)
            {
                total = total + amt;
            }

            if (i == 5)
            {
                total = total + amt;
            }

            if (i == 6)
            {
                total = total + amt;
            }

            connection.Close();
            ViewBag.TotalBalance = total;

            i++;
        }

【问题讨论】:

  • 如果SUM返回null,我想你会得到这样的错误。
  • 是的,我也注意到了。我现在正在使用 Convert.ToInt32 并且我得到了一个更详细的异常。处理潜在空值的最佳方法是什么?
  • 几乎总是与 SQL 相关的问题:不要使用字符串连接创建查询,而是使用参数化查询,因为它们会阻止 SQL 注入。

标签: c# sql-server asp.net-mvc-5


【解决方案1】:

ExecuteScalar 返回null 时,发生非法转换异常。您可以在转换为int之前检查结果是否为null

 object o = cmd.ExecuteScalar();
 int result = o == null ? 0 : (int)o;

或者你可以使用可以为空的 int int? 也可以检查它是否有值

 int? result = (int?)cmd.ExecuteScalar();
 if (!result.HasValue) result = 0;

或者即使没有找到匹配的行,您也可以调整查询以返回 0。 TSQL函数COALESCE检查第一个参数是否为NULL,如果不是则返回值,如果是则返回第二个参数的值。

 string query = "SELECT COALESCE(SUM(AMOUNT),0) FROM TRANSACTIONS_DETAIL2 WHERE TRANSACTIONS_DETAIL2.TRANS_TYPE =" + i + "AND TRANSACTIONS_DETAIL2.HOH_UPI = '185292000'";

【讨论】:

  • ExecuteScalar 将返回 null 如果结果集是绝对空的,或者DBNull,如果有行但没有什么可总结的。在您的代码中,您不处理 DBNull 的情况。我必须承认,我的回答 - 反之亦然 - 没有涵盖 null :-) 所以 - 你和我一起 - 给出了正确的答案
【解决方案2】:

根据您的评论

如果您调用ExecuteScalar,您可能会得到nullDBNull 作为回报,您应该同时检查两者。您可以先将其填充到object 类型的变量中,然后检查DBNull.Valuenull 并对此做出反应:

int amt=0;
object amtUnchecked = cmd.ExecuteScalar();
if(amtUnchecked != DBNull.Value && amtUnchecked!=null)
    amt=(int)amtUnchecked;

或者您更改 SELECT 以返回肯定为零:SELECT ISNULL(SUM(AMOUNT),0) ...

【讨论】:

  • 当我确保 sum 查询不返回空值时,该代码有效。问题在于能够控制将 amt 转换为 int 时返回的空值。有什么想法吗?
  • 错了,我不确定是隐式调用 ToString() 还是 String + int 重载了 + 运算符
  • @derpirscher,是的,你是对的,found this。我将从我的答案中删除这部分...
  • @Shnugo 我尝试使用 ISNULL,就像你回答的那样:pastebin.com/Wbvpekt4 但我收到一个异常,说“关键字'FROM'附近的语法不正确”。感谢您的帮助!
  • @vmil,您的语法不正确:ISNULL() 函数需要第二个参数(NULL 的值)和右括号:ISNULL(SUM(AMOUNT),0) FROM...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-09
  • 2013-08-27
  • 1970-01-01
  • 2020-07-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多