C# 没有返回结果时处理ExecuteScalar()

C# 没有返回结果时处理ExecuteScalar(),c#,oracle,ado.net,C#,Oracle,Ado.net,我正在使用以下SQL查询和ExecuteScalar()方法从Oracle数据库获取数据: sql = "select username from usermst where userid=2" string getusername = command.ExecuteScalar(); 它向我显示以下错误消息: System.NullReferenceException:对象引用未设置为对象的实例 当userid=2的数据库表中没有行时,就会发生此错误 我应该如何处理这种情况?首先,您应该确保

我正在使用以下SQL查询和
ExecuteScalar()
方法从Oracle数据库获取数据:

sql = "select username from usermst where userid=2"
string getusername = command.ExecuteScalar();
它向我显示以下错误消息:

System.NullReferenceException:对象引用未设置为对象的实例

userid=2的数据库表中没有行时,就会发生此错误

我应该如何处理这种情况?

首先,您应该确保您的命令对象不为null。然后,应该将命令的CommandText属性设置为sql查询。最后,您应该将返回值存储在对象变量中,并在使用它之前检查它是否为null:

command = new OracleCommand(connection)
command.CommandText = sql
object userNameObj = command.ExecuteScalar()
if (userNameObj != null)
  string getUserName = userNameObj.ToString()
 ...

我不确定VB语法,但你明白了

这可能会有帮助。。例如:

using System;
using System.Data;
using System.Data.SqlClient;

class ExecuteScalar
{
  public static void Main()
  {
    SqlConnection mySqlConnection =new SqlConnection("server=(local)\\SQLEXPRESS;database=MyDatabase;Integrated Security=SSPI;");
    SqlCommand mySqlCommand = mySqlConnection.CreateCommand();
    mySqlCommand.CommandText ="SELECT COUNT(*) FROM Employee";
    mySqlConnection.Open();

    int returnValue = (int) mySqlCommand.ExecuteScalar();
    Console.WriteLine("mySqlCommand.ExecuteScalar() = " + returnValue);

    mySqlConnection.Close();
  }
}

从这个

小小的推测:如果检查堆栈中是否存在异常,则会抛出异常,然后Oracle的ADO.NET提供程序正在读取底层行集以获取第一个值

如果没有行,则没有要查找的值

要处理这种情况,请对读卡器执行,并处理
Next()
在不匹配的情况下返回false。

以下行:

string getusername = command.ExecuteScalar();
。。。将尝试将结果隐式转换为字符串,如下所示:

string getusername = (string)command.ExecuteScalar();
如果对象为null,常规强制转换操作符将失败。 尝试使用as运算符,如下所示:

string getusername = command.ExecuteScalar() as string;
根据:

如果未找到结果集中第一行的第一列,则 返回空引用(在Visual Basic中为空)。如果值在 数据库为null,查询返回DBNull.Value

考虑以下代码段:

using (var conn = new OracleConnection(...)) {
    conn.Open();
    var command = conn.CreateCommand();
    command.CommandText = "select username from usermst where userid=2";
    string getusername = (string)command.ExecuteScalar();
}
在运行时(在ODP.NET下测试,但在任何ADO.NET提供程序下应相同),其行为如下:

string getusername = command.ExecuteScalar() as string;
  • 如果该行不存在,则
    command.ExecuteScalar()
    的结果为空,然后将其转换为空字符串并分配给
    getusername
  • 如果该行存在,但用户名为NULL(在您的数据库中可能吗?),则
    命令.ExecuteScalar()
    的结果为
    DBNull.Value
    ,从而导致
    无效的CastException
在任何情况下,
NullReferenceException
都是不可能的,因此您的问题可能存在于其他地方。

我刚才使用了以下方法:

    int? ReadTerminalID()
    {
        int? terminalID = null;

        using (FbConnection conn = connManager.CreateFbConnection())
        {
            conn.Open();
            FbCommand fbCommand = conn.CreateCommand();
            fbCommand.CommandText = "SPSYNCGETIDTERMINAL";
            fbCommand.CommandType = CommandType.StoredProcedure;

            object result = fbCommand.ExecuteScalar(); // ExecuteScalar fails on null
            if (result.GetType() != typeof(DBNull))
            {
                terminalID = (int?)result;
            }
        }

        return terminalID;
    }

在您的情况下,要么记录不存在且用户ID=2,要么第一列中可能包含空值,因为如果在SQL命令中使用的查询结果中找不到值,
ExecuteScalar()
返回
null

sql = "select username from usermst where userid=2"

string getusername = Convert.ToString(command.ExecuteScalar());

这是最简单的方法

sql = "select username from usermst where userid=2"
object getusername = command.ExecuteScalar();
if (getusername!=null)
{
    //do whatever with the value here
    //use getusername.toString() to get the value from the query
}

我将其与Microsoft应用程序块DLL(DAL操作的帮助库)一起使用


/*选择一些不存在的整数*/
intx=((int)(SQL_Cmd.ExecuteScalar()??0))

我在VS2010中看到过
string getusername=command.ExecuteScalar()
给出编译错误,
无法将类型对象隐式转换为字符串。
所以你需要写作
string getusername=command.ExecuteScalar().ToString()
当在数据库中找不到记录时,它会给出错误消息
对象引用未设置为对象的实例

当我注释'.ToString()'时,它不会给出任何错误。所以我可以说,
ExecuteScalar
不会抛出异常。我认为@Rune Grimstad给出的anserwer是正确的。

我在vb代码中使用了这个函数的返回值:

如果没有,那么 返回对象ToString() 其他的 返回“”
如果

结束,请务必在读取行之前进行检查

if (SqlCommand.ExecuteScalar() == null)
{ 

}

当连接到数据库的用户具有连接权限,但没有从数据库读取的权限时,我遇到了此问题。就我而言,我甚至不能做这样的事情:

string getusername = command.ExecuteScalar() as string;
object userNameObj=command.ExecuteScalar()


将其放入try/catch(您可能无论如何都应该这样做)是处理权限不足问题的唯一方法。

或者,您可以使用DataTable检查是否有任何行:

SqlCommand cmd = new SqlCommand("select username from usermst where userid=2", conn);
SqlDataAdapter adp = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
adp.Fill(dt);
string getusername = "";
// assuming userid is unique
if (dt.Rows.Count > 0)
    getusername = dt.Rows[0]["username"].ToString();

尝试此代码,它似乎可以解决您的问题


Dim MaxID As Integer=Convert.ToInt32(IIf(IsDBNull(cmd.ExecuteScalar()),1,cmd.ExecuteScalar())

我正在使用Oracle。 如果sql返回的数值为int,则需要使用Convert.ToInt32(对象)。下面是一个例子:

public int GetUsersCount(int userId)
{
    using (var conn = new OracleConnection(...)){
        conn.Open();
        using(var command = conn.CreateCommand()){
            command.CommandText = "select count(*) from users where userid = :userId";
            command.AddParameter(":userId", userId);            
            var rowCount = command.ExecuteScalar();
            return rowCount == null ? 0 : Convert.ToInt32(rowCount);
        }
    }
}
SQL空值

  • C#中的等效值为DBNull.Value
  • 如果一个可为null的列没有值,那么返回的就是这个值
  • SQL中的比较:
    IF(值为NULL)
  • C#中的比较:
    if(obj==DBNull.Value)
  • 在C#Quick Watch中可视为
    {}
从数据读取器读取数据时的最佳做法:

var reader = cmd.ExecuteReader();
...
var result = (reader[i] == DBNull.Value ? "" : reader[i].ToString());
根据我的经验,在某些情况下,返回的值可能会丢失,因此返回null会导致执行失败。例如

select MAX(ID) from <table name> where <impossible condition>

如果您想要
字符串
空字符串
,以防出现空字符串,如果没有任何内容,则可以中断

using (var cmd = new OdbcCommand(cmdText, connection))
{
    var result = string.Empty;
    var scalar = cmd.ExecuteScalar();
    if (scalar != DBNull.Value) // Case where the DB value is null
    {
        result = Convert.ToString(scalar); // Case where the query doesn't return any rows. 
        // Note: Convert.ToString() returns an empty string if the object is null. 
        //       It doesn't break, like scalar.ToString() would have.
    }
    return result;
}
对象对象对象名;
objUserName=command.ExecuteScalar();
if(objUserName==null)//if未找到记录ExecuteScalar返回null
{
返回“”;
}
其他的
{
if(objUserName==DBNull.Value)//如果找到记录,但记录字段中的值为null
{
返回“”;
}
其他的
{
字符串getusername=objUserName.ToString();
返回getusername;
}
}

这可能没有多大帮助,因为引发异常的是对
ExecuteScalar
的调用。嗯。。。这可能是问题所在,但海报将问题描述为“id=2时不存在行”—因此我假设数据库连接设置正确。无论如何都在更新我的答案。是的,它是有效的,但我不明白为什么我们应该避免使用executescalar()你不应该避免使用executescalar。这是建议您在执行以下操作时使用的方法:
var obj = cmd.ExecuteScalar();
var result = (obj == null ? -1 : Convert.ToInt32(obj));
using (var cmd = new OdbcCommand(cmdText, connection))
{
    var result = string.Empty;
    var scalar = cmd.ExecuteScalar();
    if (scalar != DBNull.Value) // Case where the DB value is null
    {
        result = Convert.ToString(scalar); // Case where the query doesn't return any rows. 
        // Note: Convert.ToString() returns an empty string if the object is null. 
        //       It doesn't break, like scalar.ToString() would have.
    }
    return result;
}