Недавно я наткнулся на следующую проблему:
Назначение 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