Мой 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)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";
Обратите внимание, что конкатенации строк не происходит.