Мой SQLParameter неправильно передает NULL

У меня есть эта веб-форма C#, в которой есть поле выбора даты. Если дата не установлена ​​(по умолчанию), я хочу, чтобы она передавала NULL в базу данных. Это происходит внутри моего параметризованного запроса.

SqlParameter CMActionDate = new SqlParameter();
CMActionDate.ParameterName = "@ActionDate";
if (ActionDate.Equals(""))
  {
      CMActionDate.Value = System.Data.SqlTypes.SqlDateTime.Null;
  }
  else
  {
      CMActionDate.Value = ActionDate;
  }

Когда я включаю отладку, я вижу, что дата действительно "", поэтому она входит в оператор IF и устанавливает для actiondate.value значение {Null}, как я думаю.

Тем не мение.

Когда он затем переходит к выполнению незапроса, я щелкаю увеличительное стекло и вижу следующее:

UPDATE table SET [action_date] = '' WHERE [id] = 2488

Я бы хотел увидеть вот что:

UPDATE table SET [action_date] = 'Null' WHERE [id] = 2488

Поскольку action_date на самом деле никогда не устанавливается в NULL, значение в поле datetime возвращается к «01.01.1900 12:00:00 AM», и это само по себе неудобно.

Я попытался установить для CMActionDate.Value следующие значения, но безрезультатно (я получаю тот же результат, что и выше):

  • DBNull.Value;
  • "НУЛЕВОЙ";
  • SqlDateTime.Null;
  • нулевой;

Помощь.

РЕДАКТИРОВАТЬ

Может я не понял? Да, конечно, параметризованный запрос выглядит так:

"UPDATE CM_Codebase SET [action_date] = '" + @ActionDate + "' WHERE [id] = " + @CM_id + "";

Но когда я отлаживаю эту штуку в VS, я ставлю точку останова прямо перед ExecuteNonQuery (); так что я могу видеть SQL, который он пытается запустить. Именно там я вижу фактический SQL и бит, где action_date = ''.

Это помогает?

Ответов (3)

Решение

Вы не должны видеть ни "", ни "Null". Если вы правильно используете параметризованные запросы, они должны выглядеть так:

ОБНОВЛЕНИЕ таблицы SET [action_date] = @ActionDate WHERE [id] = @ID

Весь смысл параметризированного запроса является то , что фактическое значение параметра не никогда не замещен непосредственно в строку запроса.

Ваш код запроса должен выглядеть примерно так:

string sql = "UPDATE table SET [action_date]= @ActionDate WHERE [id]= @CM_id";

using (var cn = new SqlConnection("your connection string here."))
using (var cmd = new SqlCommand(sql, cn))
{
    cmd.Parameters.Add("@ActionDate", SqlDbTypes.DateTime).Value = 
         ActionDate.Equals("")? DBNull.Value : DateTime.Parse(ActionDate);
    cmd.Parameters.Add("@CM_id", SqlDbTypes.Int).Value = 2488;

    cn.Open();
    cmd.ExecuteNonQuery();
}

Результатом этого кода является то, что параметры вашего запроса отправляются на сервер в виде данных. Ни в одном месте вашего кода C# вы никогда не сможете просмотреть строку запроса с замененными данными: она отправляется на сервер отдельно.

Это предотвращает любую возможность выполнения сервером значения параметра как кода из-за ошибки при очистке значения параметра. Данные полностью разделены, и в первую очередь их не нужно обрабатывать для этого контекста. Это также позволяет серверу кэшировать и повторно использовать план выполнения для запроса, что приводит к (небольшому) увеличению производительности.

Ваш параметризованный запрос должен показать

UPDATE table SET [action_date] = @ActionDate WHERE [id] = @id

И значение параметра должно иметь нулевое эквивалентное значение.

Ваш sql

"UPDATE CM_Codebase SET [action_date] = '" + @ActionDate + "' 
 WHERE [id] = " + @CM_id + "";

Что на самом деле не имеет смысла. Вы должны позволить sql заменять @ActionDate и @CM_ID, а не создавать динамический sql-запрос.

Ваш sql должен быть буквально:

String sql = "UPDATE table SET [action_date] = @ActionDate WHERE [id] = @CM_id"

Не должно быть конкатенации строк вокруг переменных, и они не должны заключаться в кавычки.

Ваш запрос наверняка не похож на опубликованные.

Ваш @parameter должен находиться внутри вашей строки, чтобы его можно было правильно прочитать. Вы видите ActionDate = '', потому что, скорее всего, @ActionDate не существует.

Вам нужно что-то вроде

string sql = "UPDATE CM_Codebase SET [action_date] = @ActionDate WHERE [id] = @CM_id";

Обратите внимание, что конкатенации строк не происходит.