Je reçois cette exception:
La requête paramétrée '(@Name nvarchar (8), @ type nvarchar (8), @ unités nvarchar (4000), @ rang' attend le paramètre '@units' qui n'a pas été fourni.
Mon code pour l'insertion est:
public int insertType(string name, string type, string units = "N\\A", string range = "N\\A", string scale = "N\\A", string description = "N\\A", Guid guid = new Guid())
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command = new SqlCommand();
command.CommandText = "INSERT INTO Type(name, type, units, range, scale, description, guid) OUTPUT INSERTED.ID VALUES (@Name, @type, @units, @range, @scale, @description, @guid) ";
command.Connection = connection;
command.Parameters.AddWithValue("@Name", name);
command.Parameters.AddWithValue("@type", type);
command.Parameters.AddWithValue("@units", units);
command.Parameters.AddWithValue("@range", range);
command.Parameters.AddWithValue("@scale", scale);
command.Parameters.AddWithValue("@description", description);
command.Parameters.AddWithValue("@guid", guid);
return (int)command.ExecuteScalar();
}
}
L'exception était une surprise parce que j'utilise la fonction AddWithValue
et que je m'assure d'avoir ajouté des paramètres par défaut pour la fonction.
Résolu:
Le problème était que les quelques paramètres où les chaînes vides (qui remplacent la valeur par défaut)
C'est le code de travail:
public int insertType(string name, string type, string units = "N\\A", string range = "N\\A", string scale = "N\\A", string description = "N\\A", Guid guid = new Guid())
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command = new SqlCommand();
command.CommandText = "INSERT INTO Type(name, type, units, range, scale, description, guid) OUTPUT INSERTED.ID VALUES (@Name, @type, @units, @range, @scale, @description, @guid) ";
command.Connection = connection;
command.Parameters.AddWithValue("@Name", name);
command.Parameters.AddWithValue("@type", type);
if (String.IsNullOrEmpty(units))
{
command.Parameters.AddWithValue("@units", DBNull.Value);
}
else
command.Parameters.AddWithValue("@units", units);
if (String.IsNullOrEmpty(range))
{
command.Parameters.AddWithValue("@range", DBNull.Value);
}
else
command.Parameters.AddWithValue("@range", range);
if (String.IsNullOrEmpty(scale))
{
command.Parameters.AddWithValue("@scale", DBNull.Value);
}
else
command.Parameters.AddWithValue("@scale", scale);
if (String.IsNullOrEmpty(description))
{
command.Parameters.AddWithValue("@description", DBNull.Value);
}
else
command.Parameters.AddWithValue("@description", description);
command.Parameters.AddWithValue("@guid", guid);
return (int)command.ExecuteScalar();
}
}
Essayez ce code:
SqlParameter unitsParam = command.Parameters.AddWithValue("@units", units);
if (units == null)
{
unitsParam.Value = DBNull.Value;
}
Et vous devez vérifier tous les autres paramètres pour la valeur NULL. Si elle est nulle, vous devez transmettre la valeur DBNull.Value
.
Voici un moyen d'utiliser l'opérateur de coalescence nulle:
cmd.Parameters.AddWithValue("@units", units ?? (object)DBNull.Value);
cmd.Parameters.AddWithValue("@range", range ?? (object)DBNull.Value);
cmd.Parameters.AddWithValue("@scale", scale ?? (object)DBNull.Value);
cmd.Parameters.AddWithValue("@description", description ?? (object)DBNull.Value);
Ou pour une vérification de type plus stricte:
cmd.Parameters.Add("@units", SqlDbType.Int).Value = units ?? (object)DBNull.Value;
cmd.Parameters.Add("@range", SqlDbType.Int).Value = range ?? (object)DBNull.Value;
cmd.Parameters.Add("@scale", SqlDbType.Int).Value = scale ?? (object)DBNull.Value;
cmd.Parameters.Add("@description", SqlDbType.VarChar).Value = description ?? (object)DBNull.Value;
L'opérateur doit également être chaîné:
int?[] a = { null, null, 1 };
Console.WriteLine(a[0] ?? a[1] ?? a[2]);
command.Parameters.AddWithValue ("@ Nom", (nom == null? "": nom));
Cette classe d’extension m’a été utile à quelques reprises jusqu’à présent pour ces problèmes:
public static class DbValueExtensions
{
// Used to convert values coming from the db
public static T As<T>(this object source)
{
return source == null || source == DBNull.Value
? default(T)
: (T)source;
}
// Used to convert values going to the db
public static object AsDbValue(this object source)
{
return source ?? DBNull.Value;
}
}
Vous l'utiliseriez normalement dans deux scénarios. Tout d'abord, lors de la création de paramètres pour votre requête:
var parameters = new Dictionary<string, object>
{
{ "@username", username.AsDbValue() },
{ "@password", password.AsDbValue() },
{ "@birthDate", birthDate.AsDbValue() },
};
ou lors de l'analyse des valeurs SqlReader:
while (reader.Read())
{
yield return new UserInfo(
reader["username"].As<string>(),
reader["birthDate"].As<DateTime>(),
reader["graduationDate"].As<DateTime?>(),
reader["nickname"].As<string>()
);
}
C'est une méthode à réutiliser avec plusieurs paramètres:
public void NullorEmptyParameter(QC.SqlCommand command, string at, string value)
{
if (String.IsNullOrEmpty(value))
{
command.Parameters.AddWithValue(at, DBNull.Value);
}
else
command.Parameters.AddWithValue(at, value);
}
Et vous pourrez ensuite le réutiliser pour autant de commandes et de paramètres:
NullorEmptyParameter(command, "@Idea_ID", Idea_ID);
NullorEmptyParameter(command, "@Opportunities_or_Idea", Opportunities_or_Idea);