试图从ExecuteScalar()获取值时抛出异常

本文关键字:获取 抛出异常 ExecuteScalar | 更新日期: 2023-09-27 18:11:27

在下面的代码中,语句1抛出强制类型转换异常。我想知道为什么它不开箱?
表述二是正确的,但我想知道为什么第一个是错误的?

using (IDbCommand command = connection.CreateCommand())
{
    command.CommandText = string.Format("SELECT COUNT(1) FROM {0}", tableName);
    int count = (int)command.ExecuteScalar(); //statement 1
}
//int count = Convert.ToInt32(command.ExecuteScalar()); //statement 2

试图从ExecuteScalar()获取值时抛出异常

唉,执行标量返回一个长/int64,看到你写的SQL命令,你知道返回值将是一个计算的整数(SELECT COUNT(…,还有SELECT MAX(…)

忽略其他建议,您所需要的只是强制转换。(不,这些命令永远不会返回字符串,即:"42")

int count = (int)(long)command.ExecuteScalar();

或者如果担心大的数字

long count = (long)command.ExecuteScalar();

除非出于某种奇怪的原因,您无法控制正在执行的SQL语句,否则为什么要使转换或装箱/拆箱变得复杂呢?善良的人们,kiss,代码膨胀,…然后直接回答问题

类型转换和转换不是一回事。强制转换为int型是告诉编译器,从ExecuteScalar返回的数据已经是int型,应该被放入int型变量中。

转换它将尝试获取从ExecuteScalar返回的数据(无论数据类型如何)并尝试将其转换为int。

一个常见的例子是,如果你的查询返回字符串"42"。你不能将"42"强制转换为int型,因为它是一个字符串,但你可以转换它。

如果数据库字段确实是32位有符号整数,则只能强制转换为int。如果它是长且/或无符号的,则强制转换将失败。

由于类型不太可能改变,您可以将执行和强制转换分开,并在强制转换之前设置一个断点以查看正确的类型。

这样做的原因是,一个盒装的T只能打开到TNullable<T>。在您的情况下,数字结果恰好是作为object装箱的long,因此当您使用强制转换时,它只能有效地强制转换为long,而不是int。即使一旦您将其作为long,您也可以将其强制转换为int

参见http://blogs.msdn.com/b/ericlippert/archive/2009/03/19/representation-and-identity.aspx了解更多讨论。

根据SqlCommand。如果结果为空,则返回null。不能将null强制转换为int

但是根据我的经验,在某些情况下,它也可能返回Decimal类型。但这并没有记录在那一页上。所以使用Convert。ToInt32是一个更安全的选择。

我详细介绍了Dylan Smith和Darcara。它与装箱和拆箱有关。将代码修改为:

using (System.Data.IDbCommand command = connection.CreateCommand())
{
    command.CommandText = string.Format("SELECT COUNT(1) FROM {0}", tableName);
    object count = command.ExecuteScalar();
    System.Diagnostics.Trace.WriteLine(count.GetType());
    int iCount = (int)count; //statement 1
}

count的运行时间肯定不是int。这就是为什么你得到InvalidCastException。当您打开一个值类型时,您必须将其打开为变量的实际类型。只有在开箱之后,你才能强制转换为int

请记住,语句1在这段代码中仍然失败,但是您现在可以确定返回标量的实际类型。