Подтвердить что ты не робот

Почему конструктор имени/значения SqlParameter обрабатывает 0 как null?

Я заметил странную проблему в куске кода, где adhoc SQL-запрос не выдавал ожидаемый результат, хотя его параметры соответствовали записи в источнике данных. Я решил ввести следующее тестовое выражение в ближайшее окно:

new SqlParameter("Test", 0).Value

Это дало результат null, что заставило меня почесывать голову. Кажется, что конструктор SqlParameter обрабатывает нули как нули. Следующий код дает правильный результат:

SqlParameter testParam = new SqlParameter();
testParam.ParameterName = "Test";
testParam.Value = 0;
// subsequent inspection shows that the Value property is still 0

Может ли кто-нибудь объяснить это поведение? Это как-то преднамеренно? Если это так, это потенциально опасно...

4b9b3361

Ответ 1

Как указано в документации для этого конструктора:

Когда вы указываете объект в параметре значения, SqlDbType выводится из типа объекта Microsoft.NET Framework.

Соблюдайте осторожность при использовании этой перегрузки конструктора SqlParameter, чтобы указать значения целочисленных параметров. Поскольку эта перегрузка принимает значение типа Object, вы должны преобразовать интегральное значение в Object, когда значение равно нулю, как демонстрирует следующий пример С#.

Parameter = new SqlParameter("@pname", (object)0);

Если вы не выполняете это преобразование, компилятор предполагает, что вы пытаетесь вызвать SqlParameter (строка, SqlDbType) перегрузка конструктора.

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

Причиной этого является то, что С# допускает неявное преобразование из целочисленного литерала 0 в типы перечисления (которые являются только целыми типами внизу), и это неявное преобразование приводит к тому, что конструктор (string, SqlDbType) будет лучше соответствовать перегрузке чем преобразование бокса, необходимое для преобразования int в object для конструктора (string, object).

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

Ответ 2

Хорошие практики использования типизированных данных при передаче/добавлении ваших параметров.

Ниже вы можете выполнить задачу, как показано ниже:

Для данных с строкой /varchar:

SqlParameter pVarchar = new SqlParameter
                    {
                        ParameterName = "Test",
                        SqlDbType = System.Data.SqlDbType.VarChar,
                        Value = string.Empty,
                    };

Для введенных данных:

SqlParameter pInt = new SqlParameter
                    {
                        ParameterName = "Test",
                        SqlDbType = System.Data.SqlDbType.Int,
                        Value = 0,
                    };

Вы можете изменить значение SqlDbType в соответствии с вашими использованными данными.