如何将Nullable Bit类型值传递给SQL Server存储过程?

时间:2015-09-27 07:50:09

标签: c# sql-server

我想将null值传递给where子句bit类型变量以获取表中的所有行。但是当我通过truefalse where子句应该工作时。

错误:

  

无法确定条件表达式的类型,因为   'bool?'之间没有隐式转换和'System.DBNull'

存储过程:

CREATE PROCEDURE [dbo].[SelectAllUIDs] 
    @enable bit
AS
BEGIN
    SET NOCOUNT ON;

    SELECT 
        [UID], [fEnable] [Enable],
        [AddedDate] [Added Date]
    FROM 
        [VehicleService].[dbo].[NFCCard] 
    WHERE
        fEnable = @enable OR fEnable IS NOT NULL
    ORDER BY 
        NfcKy
END

C#代码:

 public DataSet SelectUid(bool? status)
 {
        DataSet ds = new DataSet();

        try
        {
            SqlCommand com = new SqlCommand("SelectAllUIDs", con);
            com.CommandType = CommandType.StoredProcedure;
            com.Parameters.Add(new SqlParameter("@enable", SqlDbType.Bit)
                                   { Value = status != null ? status : DBNull.Value });

            SqlDataAdapter adp = new SqlDataAdapter(com);
            adp.Fill(ds);
        }
        catch (Exception ex)
        {
            ds = null;
            throw ex;
        }
        return ds;
    }

通话:

DataSet ds = SelectUid(null); // should return all rows

DataSet ds = SelectUid(true); // should return fEnable = true rows

DataSet ds = SelectUid(false); // should return fEnable = false rows

2 个答案:

答案 0 :(得分:3)

您可以使用the ?? operator为状态为null时提供替代方案。与@ user2864740评论一样,双方必须是兼容类型。这不会起作用:

var x = true ?? DBNull.Value;  // "no implicit conversion" error

??的左手值是bool,但右手值不是。所以编译器会抱怨DBNull.Value不能"隐式转换"到bool。要解决此问题,请将左侧投向object

var x = (object) true ?? DBNull.Value;

现在??会评估一个对象,该对象可以同时包含boolDNull.Value。将其应用于您的问题,您将获得:

com.Parameters.AddWithValue("@parname", (object) status ?? DBNull.Value);

答案 1 :(得分:0)

我有一个Nullable项目,上面的代码生成编译器警告并使用此模式

static object Nullable(bool? value)
{
    if (value is null)
        return DBNull.Value;
    else
        return value.Value;
}
static object Nullable(int? value)
{
    if (value is null)
        return DBNull.Value;
    else
        return value.Value;
}

无论我使用了多少可空数据类型,编译器都知道该选择什么,以便在编译期间毫无问题地得到解决。

我这样声明的参数

com.Parameters.Add(
new SqlParameter("parameterName", SqlDbType.Bit) { Value  = Nullable(visitStat.Interactive), IsNullable=true });

我希望在可能的情况下减少反射,而AddWithValue会在MS代码中引起反射,并且在编写代码时不需要使用数据类型时,通常会在参数化查询中遇到错误的数据类型,因为您知道数据类型

使用基于反射的SQLParameter构造函数不太聪明,因为当您这样做时,SQL Server会将其强制转换为执行计划中的正确数据类型,从而使其成为Row-By-Row操作。当使用TSQL数据类型(如SmallDatetime,date,TinyInt,CHAR和VarChar数据类型)时,尤其糟糕,因为它们总是出错。

您在传递字符串时会看到这一点,因为它们始终会反映在nvarchar(max)中,将索引的电子邮件字段与nvarchar(max)参数进行比较……看看at implicit conversions,我们知道它需要的数据类型,当“他们说”“数据库将变慢”(当它开始比可能容纳在内存中的微型开发人员数据库大时)时,我们需要在程序代码中键入的几个额外字符值得您解决。

仅仅因为您可以在代码中添加1个底线并不能使其表现出色