C# AddWithValue 参数为 NULL 时的异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13451085/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 08:35:59  来源:igfitidea点击:

Exception when AddWithValue parameter is NULL

c#.netado.net

提问by LCJ

I have following code for specifying parameters for SQL query. I am getting following exception when I use Code 1; but works fine when I use Code 2. In Code 2we have a check for null and hence a if..elseblock.

我有以下代码用于指定 SQL 查询的参数。我在使用时遇到以下异常Code 1;但是当我使用Code 2. 在Code 2我们检查空值,因此是一个if..else块。

Exception:

例外:

The parameterized query '(@application_ex_id nvarchar(4000))SELECT E.application_ex_id A' expects the parameter '@application_ex_id', which was not supplied.

参数化查询 '(@application_ex_id nvarchar(4000))SELECT E.application_ex_id A' 需要参数 '@application_ex_id',但未提供该参数。

Code 1:

代码 1

command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID);

Code 2:

代码 2

if (logSearch.LogID != null)
{
         command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID);
}
else
{
        command.Parameters.AddWithValue("@application_ex_id", DBNull.Value );
}

QUESTION

  1. Can you please explain why it is unable to take NULL from logSearch.LogID value in Code 1 (but able to accept DBNull)?

  2. Is there a better code to handle this?

  1. 你能解释一下为什么它不能从代码 1 中的 logSearch.LogID 值中获取 NULL(但能够接受 DBNull)?

  2. 有没有更好的代码来处理这个问题?

Reference:

参考

  1. Assign null to a SqlParameter
  2. Datatype returned varies based on data in table
  3. Conversion error from database smallint into C# nullable int
  4. What is the point of DBNull?
  1. 将 null 分配给 SqlParameter
  2. 返回的数据类型因表中的数据而异
  3. 从数据库 smallint 到 C# nullable int 的转换错误
  4. DBNull 的意义何在?

CODE

代码

    public Collection<Log> GetLogs(LogSearch logSearch)
    {
        Collection<Log> logs = new Collection<Log>();

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();

            string commandText = @"SELECT  *
                FROM Application_Ex E 
                WHERE  (E.application_ex_id = @application_ex_id OR @application_ex_id IS NULL)";

            using (SqlCommand command = new SqlCommand(commandText, connection))
            {
                command.CommandType = System.Data.CommandType.Text;

                //Parameter value setting
                //command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID);
                if (logSearch.LogID != null)
                {
                    command.Parameters.AddWithValue("@application_ex_id", logSearch.LogID);
                }
                else
                {
                    command.Parameters.AddWithValue("@application_ex_id", DBNull.Value );
                }

                using (SqlDataReader reader = command.ExecuteReader())
                {
                    if (reader.HasRows)
                    {
                        Collection<Object> entityList = new Collection<Object>();
                        entityList.Add(new Log());

                        ArrayList records = EntityDataMappingHelper.SelectRecords(entityList, reader);

                        for (int i = 0; i < records.Count; i++)
                        {
                            Log log = new Log();
                            Dictionary<string, object> currentRecord = (Dictionary<string, object>)records[i];
                            EntityDataMappingHelper.FillEntityFromRecord(log, currentRecord);
                            logs.Add(log);
                        }
                    }

                    //reader.Close();
                }
            }
        }

        return logs;
    }

采纳答案by Marc Gravell

Annoying, isn't it.

烦人是不是。

You can use:

您可以使用:

command.Parameters.AddWithValue("@application_ex_id",
       ((object)logSearch.LogID) ?? DBNull.Value);

Or alternatively, use a tool like "dapper", which will do all that messing for you.

或者,使用“dapper”之类的工具,它会为您解决所有这些麻烦。

For example:

例如:

var data = conn.Query<SomeType>(commandText,
      new { application_ex_id = logSearch.LogID }).ToList();

I'm temptedto add a method to dapper to get the IDataReader... not really sure yet whether it is a good idea.

很想为 dapper 添加一个方法来获得IDataReader......还不确定这是否是一个好主意。

回答by user1599225

some problem, allowed with Necessarily set SQLDbType

一些问题,允许有必要设置 SQLDbType

command.Parameters.Add("@Name", SqlDbType.NVarChar);
command.Parameters.Value=DBNull.Value

where SqlDbType.NVarChar you type. Necessarily set SQL type.

您键入的 SqlDbType.NVarChar 在哪里。必须设置 SQL 类型。

回答by AxiomaticNexus

I find it easier to just write an extension method for the SqlParameterCollectionthat handles null values:

我发现为SqlParameterCollection处理空值的编写扩展方法更容易:

public static SqlParameter AddWithNullableValue(
    this SqlParameterCollection collection,
    string parameterName,
    object value)
{
    if(value == null)
        return collection.AddWithValue(parameterName, DBNull.Value);
    else
        return collection.AddWithValue(parameterName, value);
}

Then you just call it like:

然后你就可以这样称呼它:

sqlCommand.Parameters.AddWithNullableValue(key, value);

回答by z00l

Just in case you're doing this while calling a stored procedure: I think it's easier to read if you declare a default value on the parameter and add it only when necessary.

以防万一您在调用存储过程时执行此操作:我认为如果您在参数上声明默认值并仅在必要时添加它,则更容易阅读。

SQL:

查询语句:

DECLARE PROCEDURE myprocedure
    @myparameter [int] = NULL
AS BEGIN

C#:

C#:

int? myvalue = initMyValue();
if (myvalue.hasValue) cmd.Parameters.AddWithValue("myparamater", myvalue);