web-dev-qa-db-fra.com

Valeur renvoyée avec String result = Une erreur Command.ExecuteScalar () se produit lorsque le résultat renvoie la valeur null

Je veux récupérer la valeur de la 1ère ligne 1ère cellule de la base de données, cela fonctionne bien avec le code ci-dessous. Mais quand il n'y a pas de résultat trouvé, il jette Exception.

Comment gérer avec DBNull.
Devrais-je changer ma requête? qui retourne une certaine valeur si aucun dossier n’est enregistré?

System.NullReferenceException: la référence à un objet n'est pas définie sur une instance d'un objet.

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;
    }
24
Satinder singh

Il n'est pas nécessaire de continuer à appeler .ToString() car getValue est déjà une chaîne.

À part cela, cette ligne pourrait éventuellement être votre problème:

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

S'il n'y a pas de lignes, .ExecuteScalar renverra null. Vous devez donc vérifier.

Par exemple:

var firstColumn = cmd.ExecuteScalar();

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

Si la première cellule renvoyée est un null, le résultat dans .NET sera DBNull.Value

Si aucune cellule n'est retournée , le résultat dans .NET sera null; vous ne pouvez pas appeler ToString() sur un null. Vous pouvez bien sûr capturer ce que ExecuteScalar renvoie et traiter les cas null/DBNull/autres séparément.

Puisque vous regroupez, etc., vous pourriez probablement avoir plus d’un groupe. Franchement, je ne suis pas sûr que ExecuteScalar soit votre meilleure option ici ...


Supplémentaire: le sql dans la question est mauvais à bien des égards:

  • injection sql
  • internationalisation (espérons que le client et le serveur s'accordent sur ce à quoi ressemble une date)
  • concaténation inutile dans des déclarations séparées

Je vous suggère fortement de paramétrer; peut-être avec quelque chose comme "pimpant" pour rendre les choses faciles:

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

tous les problèmes résolus, y compris le scénario "sans lignes". Les dates sont passées sous forme de dates (pas de chaînes); le trou d'injection est fermé à l'aide d'un paramètre. Vous obtenez également la réutilisation du plan de requête en tant que bonus supplémentaire. Le group by ici est redondant, BTW - s'il n'y a qu'un seul groupe (via la condition d'égalité), vous pouvez également sélectionner simplement COUNT(1).

18
Marc Gravell

Essaye celui-là

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

Vous pouvez utiliser comme suit

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

La valeur n'est pas null, mais DBNull.Value.

object value = cmd.ExecuteScalar();
if(value == DBNull.Value)
4
Jānis

essaye ça : 

 string getValue = Convert.ToString(cmd.ExecuteScalar());
2
Naresh Parmar

Cela devrait fonctionner:

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

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

Aussi, je suggérerais d'utiliser les paramètres dans votre requête, quelque chose comme (juste une 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 ...
1
Dimitar Dimitrov

Utiliser la fonction isnull du serveur SQL

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

Il y a une fonctionnalité avancée de c #, utilisez ce '?.' . string getValue = cmd.ExecuteScalar () ?. ToString (); merci tout.

0
Muzafar Hussain