C# AddWithValue参数为NULL时出现异常

C# AddWithValue参数为NULL时出现异常,c#,.net,ado.net,C#,.net,Ado.net,我有以下用于指定SQL查询参数的代码。当我使用代码1时,出现以下异常:;但是当我使用code 2时效果很好。在code 2中,我们检查了null,因此出现了if..else块 例外情况: 参数化查询“(@application_ex_id nvarchar(4000))SELECT E.application_ex_id A”需要未提供的参数“@application_ex_id” 代码1: command.Parameters.AddWithValue("@application_ex_id"

我有以下用于指定SQL查询参数的代码。当我使用
代码1
时,出现以下异常:;但是当我使用
code 2
时效果很好。在
code 2
中,我们检查了null,因此出现了
if..else

例外情况:

参数化查询“(@application_ex_id nvarchar(4000))SELECT E.application_ex_id A”需要未提供的参数“@application_ex_id”

代码1

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 );
}
代码2

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 );
}
问题

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

  • 有更好的代码来处理这个问题吗

  • 参考

    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 );
    }
    
  • 代码

    public Collection GetLogs(LogSearch-LogSearch)
    {
    收集日志=新收集();
    使用(SqlConnection连接=新的SqlConnection(connectionString))
    {
    connection.Open();
    string commandText=@“选择*
    来自应用程序_Ex E
    其中(E.application_ex_id=@application_ex_id或@application_ex_id为NULL)”;
    使用(SqlCommand=newsqlcommand(commandText,connection))
    {
    command.CommandType=System.Data.CommandType.Text;
    //参数值设置
    //command.Parameters.AddWithValue(“@application\u ex\u id”,logSearch.LogID);
    if(logSearch.LogID!=null)
    {
    command.Parameters.AddWithValue(“@application\u ex\u id”,logSearch.LogID);
    }
    其他的
    {
    command.Parameters.AddWithValue(“@application\u ex\u id”,DBNull.Value);
    }
    使用(SqlDataReader=command.ExecuteReader())
    {
    if(reader.HasRows)
    {
    集合entityList=新集合();
    添加(新日志());
    ArrayList records=EntityDataMappingHelper.SelectRecords(entityList,reader);
    for(int i=0;i
    很烦人,不是吗

    您可以使用:

    command.Parameters.AddWithValue("@application_ex_id",
           ((object)logSearch.LogID) ?? DBNull.Value);
    
    或者,也可以使用像“dapper”这样的工具,它可以帮你解决所有这些麻烦

    例如:

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

    我很想给dapper添加一个方法来获取
    IDataReader
    。。。还不确定这是否是个好主意。

    一些问题,必须设置SQLDbType才能允许

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

    您在其中键入SqlDbType.NVarChar。必须设置SQL类型

    我发现为处理空值的
    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);
    }
    
    那么你就这样称呼它:

    sqlCommand.Parameters.AddWithNullableValue(key, value);
    

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

    SQL:

    声明过程myprocedure
    @myparameter[int]=NULL
    作为开始
    
    C#:

    int?myvalue=initMyValue();
    if(myvalue.hasValue)cmd.Parameters.AddWithValue(“myParameter”,myvalue);
    
    你说的更好是什么意思?代码2是向数据库发送空值的正确方法。我正在考虑对参数属性进行扩展-这是对象?@Phil hmmm,是的,我明白你的意思了。。。也许
    AddWithValueAndTreatNullTheRightDamnedWay(…)
    @marcGravel您能解释一下为什么它不能从代码1中的logSearch.LogID值中获取NULL(但可以接受DBNull)?@Lijo因为参数值中的
    NULL
    表示“不发送此参数”。我怀疑这是一个糟糕的决定,只是被烤了进去。事实上,我认为大部分的
    DBNull
    都是一个从根本上说是错误的决定,这是因为@tylerH的null coale cast规则——在C#9value中可能会减弱,可以是int或int?、string、bool或bool?、DateTime或DateTime?、等等?我读了Marc的答案并思考“我想我更愿意为参数集合编写一个扩展方法”,然后我向下滚动了一根头发…(扩展方法的好处是我可以在完成所有代码更新后进行一次查找/替换)很好的解决方案…扩展方法必须在静态类中定义。也许我错了(有点像C#newbie)但是你不能更简洁地这样做:
    返回collection.AddWithValue(parameterName,value??DBNull.value);
    @TobiasFeil是的,你也可以这样做。这只是品味的问题。