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

时间:2010-01-04 11:40:37

标签: c# oracle ado.net

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

sql = "select username from usermst where userid=2"
string getusername = command.ExecuteScalar();

它显示了以下错误消息:

  

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

userid=2的数据库表中没有行时,会发生此错误 我应该如何处理这种情况?

23 个答案:

答案 0 :(得分:51)

根据MSDN documentation for DbCommand.ExecuteScalar

  

如果未找到结果集中第一行的第一列,则a   返回null引用(在Visual Basic中为Nothing)。如果值在   数据库为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提供程序下应该是相同的),它的行为如下:

  • 如果该行不存在,则command.ExecuteScalar()的结果为空,然后将其转换为空字符串并分配给getusername
  • 如果该行存在,但在用户名中为NULL(这在您的数据库中是否可能?),command.ExecuteScalar()的结果为DBNull.Value,结果为InvalidCastException

在任何情况下,都不应该NullReferenceException,所以你的问题可能在其他地方。

答案 1 :(得分:48)

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

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

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

答案 2 :(得分:22)

我刚用过这个:

    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;
    }

答案 3 :(得分:8)

以下一行:

string getusername = command.ExecuteScalar();

...将尝试隐式将结果转换为字符串,如下所示:

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

如果对象为null,则常规转换运算符将失败。 尝试使用as-operator,如下所示:

string getusername = command.ExecuteScalar() as string;

答案 4 :(得分:7)

sql = "select username from usermst where userid=2"
var _getusername = command.ExecuteScalar();
if(_getusername != DBNull.Value)
{
    getusername = _getusername.ToString();
}  

答案 5 :(得分:6)

这可能会有所帮助..例如::

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();
  }
}

来自here

答案 6 :(得分:3)

SQL NULL

  • C#中的等价物是 DBNull.Value
  • 如果NULLABLE列没有值,则返回
  • SQL中的比较:IF ( value IS 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>

上面的脚本找不到任何可以找到MAX的东西。所以它失败了。在这些情况下,我们必须比较旧的时尚方式(与C#null比较)

var obj = cmd.ExecuteScalar();
var result = (obj == null ? -1 : Convert.ToInt32(obj));

答案 7 :(得分:3)

在阅读行之前一定要检查。

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

}

答案 8 :(得分:1)

在您的情况下,userid=2中的记录不存在,或者第一列中可能包含空值,因为如果没有找到SQL命令中使用的查询结果的值,{{1} }返回ExecuteScalar()

答案 9 :(得分:1)

这是最简单的方法......

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
}

答案 10 :(得分:1)

或者,您可以使用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();

答案 11 :(得分:0)

object objUserName;
objUserName = command.ExecuteScalar();

if (objUserName == null)  //if record not found ExecuteScalar returns null
{
    return "";
}
else
{
    if (objUserName == DBNull.Value)  //if record found but value in record field is null
    {
        return "";
    }
    else
    {
        string getusername = objUserName.ToString();
        return getusername; 
    }
}

答案 12 :(得分:0)

如果您想要stringempty string以防万一,则没有任何内容可能会破坏

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;
}

答案 13 :(得分:0)

private static string GetUserNameById(string sId, string connStr)
    {
        System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(connStr);
        System.Data.SqlClient.SqlCommand command;

        try
        {
            // To be Assigned with Return value from DB
            object getusername;

            command = new System.Data.SqlClient.SqlCommand();

            command.CommandText = "Select userName from [User] where userid = @userid";

            command.Parameters.AddWithValue("@userid", sId);

            command.CommandType = CommandType.Text;

            conn.Open();

            command.Connection = conn;

            //Execute
            getusername = command.ExecuteScalar();

            //check for null due to non existent value in db and return default empty string
            string UserName = getusername == null ? string.Empty : getusername.ToString();

            return UserName;


        }
        catch (Exception ex)
        {

            throw new Exception("Could not get username", ex);
        }
        finally
        {
            conn.Close();
        }

    }

答案 14 :(得分:0)

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

object userNameObj = command.ExecuteScalar()

将它放入try / catch(你可能应该这样做)是我能看到处理权限不足问题的唯一方法。

答案 15 :(得分:0)

我在VS2010中看到过 string getusername = command.ExecuteScalar(); 给出编译错误, 无法将类型对象隐式转换为字符串。 所以你需要写 string getusername = command.ExecuteScalar().ToString(); 当在数据库中找不到记录时,它会给出错误 对象引用未设置为对象的实例 当我评论'.ToString()'时,它不会给出任何错误。所以我可以说ExecuteScalar不会抛出异常。我认为@Rune Grimstad给出的答案是正确的。

答案 16 :(得分:0)

我使用它与Microsoft Application Block DLL(它是DAL操作的帮助库)

public string getCopay(string PatientID)
{
       string sqlStr = "select ISNULL(Copay,'') Copay from Test where patient_id=" + PatientID ;
        string strCopay = (string)SqlHelper.ExecuteScalar(CommonCS.ConnectionString, CommandType.Text, sqlStr);
                if (String.IsNullOrEmpty(strCopay))
                    return "";
                else
                    return strCopay ;
}

答案 17 :(得分:0)

轻微猜想:如果检查堆栈是否存在异常,则会抛出它,然后Oracle的ADO.NET提供程序正在读取基础行集以获取第一个值。

如果没有行,则没有值可供查找。

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

答案 18 :(得分:-1)

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

如果obj&lt;&gt;什么都没有     返回obj.ToString()  其他     返回&#34;&#34;  结束如果

答案 19 :(得分:-1)

/ *选择一些不存在的int * /
int x =((int)(SQL_Cmd.ExecuteScalar()?? 0));

答案 20 :(得分:-1)

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

file_urls <- readLines ("path/to/file") node_data <- sapply(file_urls,function(i)read_html (i) %>% html_nodes (".field"))

答案 21 :(得分:-1)

我使用的是Oracle 。 如果你的sql返回数值,即int,你需要使用Convert.ToInt32(object)。以下是以下示例:

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);
        }
    }
}

答案 22 :(得分:-2)

试试这个

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

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