75

I am using the following SQL query and the ExecuteScalar() method to fetch data from an Oracle database:

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

It is showing me this error message:

System.NullReferenceException: Object reference not set to an instance of an object

This error occurs when there is no row in the database table for userid=2.
How should I handle this situation?

3
  • What ADO.NET provider are you using? ODP.NET? Commented Oct 31, 2011 at 0:54
  • 2
    the OracleCommand ExecuteScalar returns an object for the result. It's not strongly typed because the SQL statement is arbitrary, so the type isn't known until it's parsed (which is by the DB engine, not by the .NET runtime). The object returned can be null. You are assuming it is a string, and it may well be, and a lot of types can be implicitly converted to such, but it's a very dangerous assumption to make - that object can be of any type. As with any other object reference that you don't explicitly trust, first you should make sure it's not null. Commented Jun 22, 2015 at 16:10
  • A correct answer would be nice on this one. Commented Oct 16, 2015 at 20:52

23 Answers 23

61

According to MSDN documentation for DbCommand.ExecuteScalar:

If the first column of the first row in the result set is not found, a null reference (Nothing in Visual Basic) is returned. If the value in the database is null, the query returns DBNull.Value.

Consider the following snippet:

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

At run-time (tested under ODP.NET but should be the same under any ADO.NET provider), it behaves like this:

  • If the row does not exist, the result of command.ExecuteScalar() is null, which is then casted to a null string and assigned to getusername.
  • If the row exists, but has NULL in username (is this even possible in your DB?), the result of command.ExecuteScalar() is DBNull.Value, resulting in an InvalidCastException.

In any case, the NullReferenceException should not be possible, so your problem probably lies elsewhere.

Sign up to request clarification or add additional context in comments.

4 Comments

Problem elsewhere? like using getusername without checking if it's null in code he did not post? After all, a NullReferenceException implies someone tried to dereference (not assign) a null.
@iheanyi Apparently so.
This will fail if the first column of the first row contains NULL, because then ExecuteScalar returns DBNull. The line should read: string getusername = command.ExecuteScalar() as string;
@OlivierJacot-Descombes Yes, I mentioned the InvalidCastException in my answer.
58

First you should ensure that your command object is not null. Then you should set the CommandText property of the command to your sql query. Finally you should store the return value in an object variable and check if it is null before using it:

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

I'm not sure about the VB syntax but you get the idea.

4 Comments

That will probably not help a lot since it is the call to ExecuteScalar that throws the exception.
Hmm... That might be the problem, but the poster describes the problem as "no row exists ... for id = 2" - hence I assume that the database connection is setup correctly. Updating my answer anyhow.
Yess it work, But i am not getting why should we avoid using executescalar()
You shouldn't avoid using ExecuteScalar. It is the recommended method to use when you only want a single return value from a query. The problem is that it returns an Object, not a value of the type you want. The reason is that the database can contain a null value in the column and the query may not return a value at all. That is why you store the value in an object type variable that you cast to the apropriate type.
32

I just used this:

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

2 Comments

I tried your code and I get thrown an exception in the if condition statement, so I changed it simple to: if (result != null) and it worked. Still +1 for your answer. Thanks.
even with null value checking goes inside if condition. DBNull is Working! result.GetType() != typeof(DBNull)
17

The following line:

string getusername = command.ExecuteScalar(); 

... will try to implicitly convert the result to string, like below:

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

The regular casting operator will fail if the object is null. Try using the as-operator, like this:

string getusername = command.ExecuteScalar() as string; 

6 Comments

Thanks, It works, but can you compare your answer with others(Rune Grimstad,Fredrik Mörk ) I am confused now which one is best practice
If you only want to get 1 value, ExecuteScalar is a good method to use. You just have to be careful how you handle the object you get. Using the as-operator will not throw a NullReferenceException when casting null to a string.
The: object o = null; string s = (string)o; does not throw an exception, so I'm wondering if the exception was really because of ExecuteScalar() returning a null? @HemantKothiyal did you actually test this in run-time and confirmed that replacing a cast with as stops the exception? And did you get the expected result in getusername?
@HemantKothiyal BTW, string getusername = command.ExecuteScalar(); does not compile - error CS0266: Cannot implicitly convert type 'object' to 'string'. An explicit conversion exists (are you missing a cast?) Could you post the actual code you have used?
@HemantKothiyal check the msdn about "as" operator ( msdn.microsoft.com/zh-tw/library/cscsdfbt.aspx ) The as operator is like a cast operation.However, if the conversion isn't possible, as returns null instead of raising an exception.Consider the following example:
|
10
sql = "select username from usermst where userid=2" var _getusername = command.ExecuteScalar(); if(_getusername != DBNull.Value) { getusername = _getusername.ToString(); } 

Comments

9

Check out the example below:

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

from this here

Comments

7

SQL NULL value

  • equivalent in C# is DBNull.Value
  • if a NULLABLE column has no value, this is what is returned
  • comparison in SQL: IF ( value IS NULL )
  • comparison in C#: if (obj == DBNull.Value)
  • visually represented in C# Quick-Watch as {}

Best practice when reading from a data reader:

var reader = cmd.ExecuteReader(); ... var result = (reader[i] == DBNull.Value ? "" : reader[i].ToString()); 

In my experience, there are some cases the returned value can be missing and thus execution fails by returning null. An example would be

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

The above script cannot find anything to find a MAX in. So it fails. In these such cases we must compare the old fashion way (compare with C# null)

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

Comments

5

Always have a check before reading row.

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

2 Comments

for the simple and logical answer +1 .
wouldn't this double execute the query? check if result of query is not null, if it's not, then execute the query assigning to var?
5

If you either want the string or an empty string in case something is null, without anything can break:

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

Comments

2

This is the easiest way to do this...

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 } 

Comments

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

1 Comment

While code-only answers might solve the problem at hand (even if it is eleven years old), it will not help future readers to understand what the problem is and why it can be solved this way. So please do also add an explanation (not just comments in your code-only answer).
1

In your case either the record doesn't exist with the userid=2 or it may contain a null value in first column, because if no value is found for the query result used in SQL command, ExecuteScalar() returns null.

Comments

1

Alternatively, you can use DataTable to check if there's any row:

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

Comments

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

2 Comments

How does this fix OPs problem?
If he wants to avoid exception then he needs to handle the scenario where the query might return null value.
0

Slight conjecture: if you check the stack for the exception, it is being thrown then the ADO.NET provider for Oracle is reading the underlying rowset to get the first value.

If there is no row, then there is no value to find.

To handle this case execute for a reader and handle Next() returning false for the case of no match.

Comments

0

I Use it Like This with Microsoft Application Block DLL (Its a help library for DAL operations)

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

Comments

0

I have seen in VS2010 string getusername = command.ExecuteScalar(); gives compilation error, Cannot implicitly convert type object to string. So you need to write string getusername = command.ExecuteScalar().ToString(); when there is no record found in database it gives error Object reference not set to an instance of an object and when I comment '.ToString()', it is not give any error. So I can say ExecuteScalar not throw an exception. I think anserwer given by @Rune Grimstad is right.

Comments

0

I had this issue when the user connecting to the database had CONNECT permissions, but no permissions to read from the database. In my case, I could not even do something like this:

object userNameObj = command.ExecuteScalar()

Putting this in a try/catch (which you should probably be doing anyway) was the only way I could see to handle the insufficient permission issue.

Comments

-1

/* Select some int which does not exist */
int x = ((int)(SQL_Cmd.ExecuteScalar() ?? 0));

Comments

-1

I used this in my vb code for the return value of a function:

If obj <> Nothing Then Return obj.ToString() Else Return "" End If

Comments

-1

Try this code, it appears to solve your problem.

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

Comments

-1

I'm using Oracle. If your sql returns numeric value, which is int, you need to use Convert.ToInt32(object). Here is the example below:

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

Comments

-2

Try this

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

1 Comment

Would you be willing to explain more about this code, and why it is an answer to the question posed?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.