Я устал от написания следующего кода:
/* 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.
}*/
Так, я записал это:
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));
Если бы это - хороший способ пойти о выполнении этого затем, что Вы предложили бы в качестве имени метода? DBNullValueorStringIfNotNull является немного подробным и сбивает с толку.
Я также открыт для способов облегчить эту проблему полностью. Я хотел бы сделать это:
myCmd.Parameters.Add("@MiddleName", MiddleName==null ? DBNull.Value : MiddleName);
но это не будет работать потому что "Оператор'??' не может быть применен к операндам типа 'строка и 'Система. DBNull'".
У меня есть C# 3.5 и SQL Server 2005 в моем распоряжении, если он имеет значение.
Приведите любое из ваших значений к объекту
, и он будет компилироваться.
myCmd.Parameters.Add("@MiddleName", MiddleName==null ? (object)DBNull.Value : MiddleName);
Да, мы все хотели бы сделать myCmd.Parameters.Add ("@ MiddleName", MiddleName ?? DBNull.Value);
. Или, что еще лучше, пусть этот чертов уровень SqlClient понимает, что CLR null
должен отображаться в DBNull.Value
при добавлении параметра. К сожалению, система типов .Net закрывает первую альтернативу, а реализация SqlClient закрывает вторую.
Я бы выбрал хорошо известное имя функции, например Coalesce или IsNull . Любой разработчик БД сразу узнает, что он делает, по названию.
Я бы предпочел дать вам два совершенно разных предложения:
Используйте ORM. Существует множество ненавязчивых инструментов ORM.
Напишите свою собственную оболочку для построения команд с более понятным интерфейсом. Что-то вроде:
публичный класс MyCommandRunner {
приватный SqlCommand cmd;
публичный MyCommandRunner (string commandText) {
cmd = new SqlCommand (commandText); { {1}}}
public void AddParameter (строковое имя, строковое значение) {
if (value == null)
cmd.Parameters.Add (name , DBNull.Value);
else
cmd.Parameters.Add (name, value);
}
// ... больше AddParameter перегружает
}
Если вы переименуете свои методы AddParameter
только в Add
, вы сможете использовать его очень удобно:
var cmd = new MyCommand("INSERT ...")
{
{ "@Param1", null },
{ "@Param2", p2 }
};
Я бы предложил использовать свойства, допускающие значение NULL, вместо общедоступных полей и метода 'AddParameter' (не знаю, оптимизирован ли этот код или правильный, просто вне в верхней части моей головы):
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);
Лично я бы сделал это с методом расширения (убедитесь, что он входит в статический класс)
public static object GetStringOrDBNull(this string obj)
{
return string.IsNullOrEmpty(obj) ? DBNull.Value : (object) obj
}
Тогда у вас будет
myCmd.Parameters.Add("@MiddleName", MiddleName.GetStringOrDBNull());