当给SqlParameter赋值为null时,它会“消失”吗?

3
我最近遇到了以下问题:
将一个 null 赋值给 SqlParameter 的 Value 属性似乎会导致该参数在查询中被省略,而不是传递 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

我运行了以下代码:

我运行了以下代码:

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,但是使用null调用ExecuteStoredProcedure()会导致以下错误:

System.Data.SqlClient.SqlException (0x80131904):存储过程或函数“TheStoredProcedure”需要提供未提供的参数“@TheValue”。

从文档中可以看出,当您希望在存储过程中使用参数的默认值时,应使用null

此属性可以设置为null或Value。使用Value发送NULL值作为参数的值。使用null或不设置Value以使用参数的默认值。

https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlparameter.value?view=netframework-4.7.2#System_Data_SqlClient_SqlParameter_Value 由于我的参数没有默认值,因此应该期望某种错误。然而,我们得到的似乎是误导性的:错误指示数据库端未收到参数,而不是指示该参数上存在意外值(或者更确切地说:缺少值)的错误。
或者这实际上是预期的行为,即将Value设置为null有效地排除了将参数传递给服务器以执行命令的可能性?
更新20.01.2010
文档已经更新:

此属性可以设置为nullDBNull.Value。使用DBNull.Value发送NULL值作为参数的值。使用null或不设置Value以使用参数的默认值。

这也许不是非常清晰,但至少是明确的。
关键在于,如果SqlParamer对象的Value属性为null,则存储过程定义的参数的默认值会起作用,我只能假设这是通过在查询执行时省略它来实现的。
我想要从中学到的教训是,始终要在可选参数上定义存储过程的默认值。
-S

请点击此处查看答案:https://dev59.com/_0vSa4cB1Zd3GeqPenrd - undefined
使用 DbNull.Value 代替传递 null - undefined
@shahkalpesh 这不是一个解决方案。这只是掩盖了问题,而不是解决它。 - undefined
可能是将null赋值给SqlParameter的重复问题。 - undefined
可能是将NULL值分配给SqlParameter的最佳方法的重复问题。 - undefined
显示剩余7条评论
2个回答

3

不要将值设置为null,如果您想将NULL传递给存储过程

文档几乎正确。在短语中:

使用Value将NULL值作为参数的值发送。

链接指向DbNull.Value。这是文档错误。

传递null而不是DbNull.Value意味着您想使用存储过程的默认参数。文档的这一部分是正确的:

使用null或不设置Value以使用参数的默认值。

更新

我刚刚添加了Github问题


1

SqlParameter.Value属性

此属性可以设置为null或DBNull.Value。使用DBNull.Value将NULL值作为参数的值发送。使用null或不设置Value以使用参数的默认值

因此,对于value = null,您必须设置参数的默认值。

CREATE PROCEDURE TheStoredProcedure
    @TheValue varchar(50) = NULL

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接