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.
Convertissez l'une de vos valeurs en object
et elle sera compilée.
myCmd.Parameters.Add("@MiddleName", MiddleName==null ? (object)DBNull.Value : MiddleName);
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);
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());
myCmd.Parameters.Add("@MiddleName", MiddleName ?? (object)DBNull.Value);
@David Merci pour votre suggestion. La méthode suivante fonctionne très bien!
MiddleName ?? (object)DBNull.Value
Je préfère vous donner deux suggestions totalement différentes:
Utilisez un ORM. Il existe de nombreux outils ORM non intrusifs.
É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 }
};
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);
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.