web-dev-qa-db-fra.com

Comment paramétrer une chaîne nulle avec DBNull.Value clairement et rapidement

Je me suis lassé d'écrire le code suivant:

/* Commenting out irrelevant parts
public string MiddleName;
public void Save(){
    SqlCommand = new SqlCommand();
    // blah blah...boring INSERT statement with params etc go here. */
    if(MiddleName==null){
        myCmd.Parameters.Add("@MiddleName", DBNull.Value);
    }
    else{
        myCmd.Parameters.Add("@MiddleName", MiddleName);
    }
    /*
    // more boring code to save to DB.
}*/

J'ai donc écrit ceci:

public static object DBNullValueorStringIfNotNull(string value)
{
    object o;
    if (value == null)
    {
        o = DBNull.Value;
    }
    else
    {
        o = value;
    }
    return o;
}

// which would be called like:
myCmd.Parameters.Add("@MiddleName", DBNullValueorStringIfNotNull(MiddleName));

Si c'est une bonne façon de procéder, que suggéreriez-vous comme nom de méthode? DBNullValueorStringIfNotNull est un peu bavard et déroutant .

Je suis également ouvert aux moyens de résoudre entièrement ce problème. J'AIMERAIS faire ça:

myCmd.Parameters.Add("@MiddleName", MiddleName==null ? DBNull.Value : MiddleName);

mais cela ne fonctionnera pas parce que "l'opérateur" ?? " ne peut pas être appliqué aux opérandes de type 'chaîne et' System.DBNull '".

J'ai C # 3.5 et SQL Server 2005 à ma disposition si cela est important.

36
David Murdoch

Convertissez l'une de vos valeurs en object et elle sera compilée.

myCmd.Parameters.Add("@MiddleName", MiddleName==null ? (object)DBNull.Value : MiddleName);
56
Adam Robinson

Vous pouvez éviter la conversion explicite en object en utilisant SqlString.Null au lieu de DBNull.Value:

MiddleName ?? SqlString.Null

Il existe des types correspondants pour int, datetime, etc. Voici un extrait de code avec quelques autres exemples:

 cmd.Parameters.AddWithValue("@StartDate", StartDate ?? SqlDateTime.Null);
 cmd.Parameters.AddWithValue("@EndDate", EndDate ?? SqlDateTime.Null);
 cmd.Parameters.AddWithValue("@Month", Month ?? SqlInt16.Null);
 cmd.Parameters.AddWithValue("@FormatID", FormatID ?? SqlInt32.Null);
 cmd.Parameters.AddWithValue("@Email", Email ?? SqlString.Null);
 cmd.Parameters.AddWithValue("@Zip", Zip ?? SqlBoolean.Null);
19
Sergey K

Personnellement, c'est ce que je ferais avec une méthode d'extension (assurez-vous que cela va dans une classe statique)

public static object GetStringOrDBNull(this string obj)
{
    return string.IsNullOrEmpty(obj) ? DBNull.Value : (object) obj
}

Ensuite, vous auriez

myCmd.Parameters.Add("@MiddleName", MiddleName.GetStringOrDBNull());
12
Chris Marisic
myCmd.Parameters.Add("@MiddleName", MiddleName ?? (object)DBNull.Value);
6

@David Merci pour votre suggestion. La méthode suivante fonctionne très bien!

MiddleName ?? (object)DBNull.Value
2
Sagar

Je préfère vous donner deux suggestions totalement différentes:

  1. Utilisez un ORM. Il existe de nombreux outils ORM non intrusifs.

  2. Écrivez votre propre wrapper pour construire des commandes, avec une interface plus propre. Quelque chose comme:

    public class MyCommandRunner {
      private SqlCommand cmd;
    
      public MyCommandRunner(string commandText) {
        cmd = new SqlCommand(commandText);
      }
    
      public void AddParameter(string name, string value) {
        if (value == null)
         cmd.Parameters.Add(name, DBNull.Value);
        else
          cmd.Parameters.Add(name, value);
      }
    
      // ... more AddParameter overloads
    }
    

Si vous renommez vos méthodes AddParameter en seulement Add, vous pouvez l'utiliser de manière très simple:

var cmd = new MyCommand("INSERT ...")
  {
    { "@Param1", null },
    { "@Param2", p2 }
  };
1
Fábio Batista

Je suggérerais d'utiliser des propriétés nullables au lieu des champs publics et une méthode 'AddParameter' (je ne sais pas si ce code est optimisé ou correct, juste en haut de ma tête):


private string m_MiddleName;

public string MiddleName
{
  get { return m_MiddleName; }
  set { m_MiddleName = value; }
}

.
.
.

public static void AddParameter(SQLCommand cmd, string parameterName, SQLDataType dataType, object value)
{
  SQLParameter param = cmd.Parameters.Add(parameterName, dataType);

  if (value is string) { // include other non-nullable datatypes
    if (value == null) {
      param.value = DBNull.Value;
    } else {
      param.value = value;
    }
  } else { 

    // nullable data types
    // UPDATE: HasValue is for nullable, not object type
    if (value.HasValue) // {{{=====================================================
    {
          param.value = value;
    } else 
    {
          param.value = DBNull.Value;
    }
  }
}

.
.
.
AddParameter(cmd, "@MiddleName", SqlDbType.VarChar, MiddleName);

1
user113476

Ouais, nous aimerions tous faire myCmd.Parameters.Add("@MiddleName", MiddleName ?? DBNull.Value);. Ou mieux encore, faites comprendre à la couche SqlClient freakin que CLR null doit être mappé sur DBNull.Value lors de l'ajout d'un paramètre. Malheureusement, le système de type .Net ferme la première alternative et l'implémentation de SqlClient ferme la seconde.

J'irais avec un nom de fonction bien connu, comme Coalesce ou IsNull . Tout développeur de base de données reconnaîtra ce qu'il fait en un instant, à partir du seul nom.

1
Remus Rusanu