Satinder singh
Satinder singh

Reputation: 10198

Return value using String result=Command.ExecuteScalar() error occurs when result returns null

I want to fetch 1st row 1st cell value from database it works well with below code . But when there is no result found it throws Exception.

How to handle with DBNull .
Should i change my query ? which return some value if theirs no record ?

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

Code:

    public string absentDayNo(DateTime sdate, DateTime edate, string idemp)
    { 
       string result="0";
       string myQuery="select COUNT(idemp_atd) absentDayNo from td_atd where ";
       myQuery +=" absentdate_atd between '"+sdate+"' and '"+edate+" ";
       myQuery +=" and idemp_atd='"+idemp+"' group by idemp_atd ";

       SqlCommand cmd = new SqlCommand(myQuery, conn);
       conn.Open();
//System.NullReferenceException occurs when their is no data/result
       string getValue = cmd.ExecuteScalar().ToString();
         if (getValue != null)
         {
            result = getValue.ToString();
         }
         conn.Close();
        return result;
    }

Upvotes: 35

Views: 228605

Answers (11)

Muzafar Hussain
Muzafar Hussain

Reputation: 11

There is a advance feature of c#, use that '?.' . string getValue = cmd.ExecuteScalar()?.ToString(); thants all.

Upvotes: 0

Ramgy Borja
Ramgy Borja

Reputation: 2458

Try this one, if null set 0 or something

return command.ExecuteScalar() == DBNull.Value ? 0 : (double)command.ExecuteScalar();

Upvotes: 0

hussien
hussien

Reputation: 1

Use SQL server isnull function

public string absentDayNo(DateTime sdate, DateTime edate, string idemp)
{ 
    string result="0";
    string myQuery="select isnull(COUNT(idemp_atd),0) as absentDayNo from td_atd where ";
    myQuery +=" absentdate_atd between '"+sdate+"' and '"+edate+" ";
    myQuery +=" and idemp_atd='"+idemp+"' group by idemp_atd ";

    SqlCommand cmd = new SqlCommand(myQuery, conn);
    conn.Open();
    //System.NullReferenceException occurs when their is no data/result
    string getValue = cmd.ExecuteScalar().ToString();
    if (getValue != null)
    {
        result = getValue.ToString();
    }
    conn.Close();
    return result;
}

Upvotes: 0

resolv
resolv

Reputation: 47

To work with NpgsqlCommand or the standard sqlCommand use:

int result = int.Parse(cmd.ExecuteScalar().ToString());

Upvotes: -1

Rajeev Kumar
Rajeev Kumar

Reputation: 4963

Try this one

var getValue = cmd.ExecuteScalar();    
conn.Close();
return (getValue == null) ? string.Empty : getValue.ToString();

Upvotes: 9

Jānis
Jānis

Reputation: 2266

Value is not null, but DBNull.Value.

object value = cmd.ExecuteScalar();
if(value == DBNull.Value)

Upvotes: 7

Marc Gravell
Marc Gravell

Reputation: 1062965

If the first cell returned is a null, the result in .NET will be DBNull.Value

If no cells are returned, the result in .NET will be null; you cannot call ToString() on a null. You can of course capture what ExecuteScalar returns and process the null / DBNull / other cases separately.

Since you are grouping etc, you presumably could potentially have more than one group. Frankly I'm not sure ExecuteScalar is your best option here...


Additional: the sql in the question is bad in many ways:

  • sql injection
  • internationalization (let's hope the client and server agree on what a date looks like)
  • unnecessary concatenation in separate statements

I strongly suggest you parameterize; perhaps with something like "dapper" to make it easy:

int count = conn.Query<int>(
  @"select COUNT(idemp_atd) absentDayNo from td_atd
    where absentdate_atd between @sdate and @edate
    and idemp_atd=@idemp group by idemp_atd",
    new {sdate, edate, idemp}).FirstOrDefault();

all problems solved, including the "no rows" scenario. The dates are passed as dates (not strings); the injection hole is closed by use of a parameter. You get query-plan re-use as an added bonus, too. The group by here is redundant, BTW - if there is only one group (via the equality condition) you might as well just select COUNT(1).

Upvotes: 22

Dimitar Dimitrov
Dimitar Dimitrov

Reputation: 15148

This should work:

var result = cmd.ExecuteScalar();
conn.Close();

return result != null ? result.ToString() : string.Empty;

Also, I'd suggest using Parameters in your query, something like (just a suggestion):

var cmd = new SqlCommand
{
    Connection = conn,
    CommandType = CommandType.Text,
    CommandText = "select COUNT(idemp_atd) absentDayNo from td_atd where absentdate_atd between @sdate and @edate and idemp_atd=@idemp group by idemp_atd"
};

cmd.Parameters.AddWithValue("@sdate", sdate);
cmd.Parameters.AddWithValue("@edate", edate);
// etc ...

Upvotes: 1

Naresh Parmar
Naresh Parmar

Reputation: 462

try this :

 string getValue = Convert.ToString(cmd.ExecuteScalar());

Upvotes: 2

Darren
Darren

Reputation: 70728

There is no need to keep calling .ToString() as getValue is already a string.

Aside that, this line could possibly be your problem:

 string getValue = cmd.ExecuteScalar().ToString();  

If there are no rows .ExecuteScalar will return null so you need to do some checking.

For instance:

var firstColumn = cmd.ExecuteScalar();

if (firstColumn != null) {
    result = firstColumn.ToString();
}

Upvotes: 69

Saravanan
Saravanan

Reputation: 7854

You can use like the following

string result = null;
object value = cmd.ExecuteScalar();
 if (value != null)
 {
    result = value.ToString();
 }     
 conn.Close();
return result;

Upvotes: 5

Related Questions