C# ADO.NET: nulls и DbNull-есть ли более эффективный синтаксис?
у меня есть DateTime?
что я пытаюсь вставить в поле с помощью DbParameter
. Я создаю параметр так:
DbParameter datePrm = updateStmt.CreateParameter();
datePrm.ParameterName = "@change_date";
и тогда я хочу поставить значение DateTime?
на dataPrm.Value
С учетом null
s.
сначала я думал, что буду умным:
datePrm.Value = nullableDate ?? DBNull.Value;
но это не удается с ошибкой
оператора??'не может применяться к операндам типа 'System.Датавремя?' и - Система.Значение dbnull'
поэтому я думаю, что это работает, только если второй аргумент является ненулевой версией первого аргумента. Тогда я пошел за:
datePrm.Value = nullableDate.HasValue ? nullableDate.Value : DBNull.Value;
но это не работает:
тип условного выражения не может быть определена, поскольку нет неявного преобразования между 'системой.DateTime " и " система.Значение dbnull'
но я не хочу конвертировать между этими типами!
пока единственное, что я могу получить на работу:
if (nullableDate.HasValue)
datePrm.Value = nullableDate.Value;
else
datePrm.Value = DBNull.Value;
это действительно единственный способ написать это? Есть ли способ заставить однострочный оператор работать с помощью троичного оператора?
обновление: я действительно не понимаю, почему ?? версия не работает. MSDN говорит:
The ?? оператор возвращает левый операнд, если он не null, иначе возвращает правый операнд.
это именно то, что я хочу!
обновление 2: Ну, в конце концов, это было очевидно:
datePrm.Value = nullableDate ?? (object)DBNull.Value;
6 ответов
Ах-ха! Я нашел еще более эффективное решение, чем @Trebz!
datePrm.Value = nullableDate ?? (object)DBNull.Value;
Если вы используете C# 3.0, вы можете создать метод расширения, чтобы сделать это легко:
public static class DBNullableExtensions
{
public static object ToDBValue<T>(this Nullable<T> value) where T:struct
{
return value.HasValue ? (object)value.Value : DBNull.Value;
}
}
class Program
{
static void Main(string[] args)
{
int? x = null;
Console.WriteLine( x.ToDBValue() == DBNull.Value );
}
}
Это будет работать, если вы использовали
datePrm.Value = nullableDate.HasValue ? (object)nullableDate.Value : DBNull.Value;
Если вы используете SQLServer, то System.Data.SqlTypes
пространство имен содержит классы, которые позволяют избежать назойливого типа литья. Например вместо этого:
var val = (object) "abc" ?? DBNull.Value;
можно написать так:
var val = "abc" ?? SqlString.Null;
Я думаю, что ошибка со второй попыткой связана с nullableDate.Значение и DBNull.Значение-это разные типы, и тернарный оператор должен выбрать один тип для возврата в обоих случаях. У меня нет среды, чтобы проверить это, но я думаю, что это должно работать для вас:
datePrm.Value = nullableDate.HasValue ? (object)nullableDate.Value : (object)DBNull.Value;
Как я это делаю, у меня есть статический класс утилиты, который просто проходит и проверяет, является ли значение параметра нулевым, затем я устанавливаю значение для выполнения DBNull. Я просто делаю это перед тем, как вызвать казнь.