SqlParameter «исчезает», когда ему присваивается значение null? - PullRequest
0 голосов
/ 07 декабря 2018

Недавно я наткнулся на следующую проблему:

Назначение null свойству Value свойства SqlParameter приводит к тому, что параметр пропускается в запросе, а не передается NULL.Это приводит к потенциально вводящему в заблуждение сообщению об ошибке, когда хранимая процедура не имеет значения по умолчанию для параметра.

У меня есть таблица базы данных со столбцом, который принимает NULL.

USE [TheDatabase]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[TheTable](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [TheValue] [varchar](50) NULL,
 CONSTRAINT [PK_TheTable] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

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

USE [TheDatabase]
GO

CREATE PROCEDURE TheStoredProcedure
    @TheValue varchar(50)
AS
BEGIN
    INSERT INTO TheTable (TheValue) VALUES (@TheValue);
END
GO

Выполнение хранимой процедуры со значением и с NULL отлично работает:

USE [TheDatabase]
GO

EXEC [dbo].[TheStoredProcedure] @TheValue = 'A string for Algernon'
GO

EXEC [dbo].[TheStoredProcedure] @TheValue = NULL
GO

Iзапустите следующий код:

using System;
using System.Data;
using System.Data.SqlClient;

class Program
{
    static void Main(string[] args)
    {
        ExecuteStoredProcedure("A string for Algernon");

        ExecuteStoredProcedure(DBNull.Value);

        ExecuteStoredProcedure(null);

        Console.ReadKey();
    }

    private static void ExecuteStoredProcedure(object value)
    {
        using (var connection = new SqlConnection("Server=TheServer;Database=TheDatabase;Persist Security Info=False;Integrated Security=true;"))
        {
            connection.Open();
            using (var sqlCommand = new SqlCommand("TheStoredProcedure", connection) {CommandType = CommandType.StoredProcedure})
            {
                sqlCommand.Parameters.Add(new SqlParameter("@TheValue", SqlDbType.VarChar, 50) {Value = value});

                try
                {
                    sqlCommand.ExecuteNonQuery();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }
        }

        Console.WriteLine(DateTime.Now);
    }
}

Первые два вызова метода выполняются нормально: первый добавляет строку в таблицу, второй добавляет NULL, но вызывает ExecuteStoredProcedure() с результатами nullв следующей ошибке:

System.Data.SqlClient.SqlException (0x80131904): Процедура или функция 'TheStoredProcedure' ожидает параметр '@TheValue', который не был предоставлен.

Из документации видно, что вы должны использовать null, если хотите использовать значение параметра по умолчанию в хранимой процедуре.

Это свойство может быть установлено в нуль или значение.Используйте Value для отправки значения NULL в качестве значения параметра.Используйте null или не устанавливайте Value для использования значения по умолчанию для параметра.

https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlparameter.value?view=netframework-4.7.2#System_Data_SqlClient_SqlParameter_Value

Поскольку мой параметр не имеет значение по умолчанию,следует ожидать какой-то ошибки.Однако то, что мы получаем, кажется вводящим в заблуждение: ошибка, указывающая на то, что параметр не был получен на стороне базы данных, в отличие от ошибки, указывающей на неожиданное значение (или, скорее: отсутствие значения) для этого параметра.действительно ли это ожидаемое поведение, что установка значения null фактически исключает передачу параметра на сервер при выполнении команды?

-S

Ответы [ 2 ]

0 голосов
/ 07 декабря 2018

Не установите значение null, если вы хотите передать NULL хранимой процедуре

Документы почти правильные.В фразе:

Используйте Значение , чтобы отправить значение NULL в качестве значения параметра.

Ссылка указывает на DBNull.Value .Это ошибка документации

Передача null вместо DbNull.Value означает, что вы хотите использовать параметр по умолчанию хранимой процедуры.Эта часть документа является правильной:

Использовать ноль или не устанавливать значение для использования значения по умолчанию для параметра.

Обновление

Я только что добавил проблему Github для этого

0 голосов
/ 07 декабря 2018

Свойство SqlParameter.Value

Это свойство может иметь значение null или DBNull.Value.Используйте DBNull.Value для отправки значения NULL в качестве значения параметра. Использовать ноль или не устанавливать значение для использования значения по умолчанию для параметра .

Так что для value = null необходимо установить значение по умолчанию для вашего патаметра.

CREATE PROCEDURE TheStoredProcedure
    @TheValue varchar(50) = NULL
...