J'ai le code suivant pour spécifier les paramètres pour la requête SQL. Je reçois l'exception suivante lorsque j'utilise Code 1
; mais fonctionne bien quand j’utilise Code 2
. Dans Code 2
nous avons un contrôle pour null et donc un if..else
bloc.
Exception:
La requête paramétrée '(@application_ex_id nvarchar (4000)) SELECT E.application_ex_id A' attend le paramètre '@application_ex_id', qui n'a pas été fourni.
Code 1 :
command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID);
Code 2 :
if (logSearch.LogID != null)
{
command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID);
}
else
{
command.Parameters.AddWithValue("@application_ex_id", DBNull.Value );
}
[~ # ~] question [~ # ~]
Pouvez-vous s'il vous plaît expliquer pourquoi il est impossible de prendre NULL à partir de la valeur logSearch.LogID dans le code 1 (mais capable d'accepter DBNull)?
Y at-il un meilleur code pour gérer cela?
Référence :
CODE
public Collection<Log> GetLogs(LogSearch logSearch)
{
Collection<Log> logs = new Collection<Log>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string commandText = @"SELECT *
FROM Application_Ex E
WHERE (E.application_ex_id = @application_ex_id OR @application_ex_id IS NULL)";
using (SqlCommand command = new SqlCommand(commandText, connection))
{
command.CommandType = System.Data.CommandType.Text;
//Parameter value setting
//command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID);
if (logSearch.LogID != null)
{
command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID);
}
else
{
command.Parameters.AddWithValue("@application_ex_id", DBNull.Value );
}
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
Collection<Object> entityList = new Collection<Object>();
entityList.Add(new Log());
ArrayList records = EntityDataMappingHelper.SelectRecords(entityList, reader);
for (int i = 0; i < records.Count; i++)
{
Log log = new Log();
Dictionary<string, object> currentRecord = (Dictionary<string, object>)records[i];
EntityDataMappingHelper.FillEntityFromRecord(log, currentRecord);
logs.Add(log);
}
}
//reader.Close();
}
}
}
return logs;
}
Ennuyant, n'est ce pas.
Vous pouvez utiliser:
command.Parameters.AddWithValue("@application_ex_id",
((object)logSearch.LogID) ?? DBNull.Value);
Ou encore, utilisez un outil comme "dapper", qui fera tout ce bazar pour vous.
Par exemple:
var data = conn.Query<SomeType>(commandText,
new { application_ex_id = logSearch.LogID }).ToList();
Je suis tenté d'ajouter une méthode à dapper pour obtenir le IDataReader
... je ne sais pas encore si c'est une bonne idée.
Je trouve plus facile d'écrire une méthode d'extension pour le SqlParameterCollection
qui gère les valeurs nulles:
public static SqlParameter AddWithNullableValue(
this SqlParameterCollection collection,
string parameterName,
object value)
{
if(value == null)
return collection.AddWithValue(parameterName, DBNull.Value);
else
return collection.AddWithValue(parameterName, value);
}
Ensuite, vous appelez juste comme:
sqlCommand.Parameters.AddWithNullableValue(key, value);
Juste au cas où vous le feriez en appelant une procédure stockée: je pense qu’il est plus facile de lire si vous déclarez une valeur par défaut sur le paramètre et ne l’ajoutez que lorsque cela est nécessaire.
Par exemple: (sql)
DECLARE PROCEDURE myprocedure
@myparameter [int] = NULL
AS BEGIN
(c #)
int? myvalue = initMyValue();
if (myvalue.hasValue) cmd.Parameters.AddWithValue("myparamater", myvalue);
Je sais que c'est vieux, mais je trouve cela utile et je voulais le partager.
un problème, autorisé avec Définir nécessairement SQLDbType
command.Parameters.Add("@Name", SqlDbType.NVarChar);
command.Parameters.Value=DBNull.Value
où vous tapez SqlDbType.NVarChar. Définit nécessairement le type SQL. Enjou