简体   繁体   English

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

[英]How to pass Nullable Bit type value into to SQL Server stored procedure?

I want to pass null value to where clause bit type variable to get all rows in a table.我想将null值传递给 where 子句bit类型变量以获取表中的所有行。 But also when I pass true or false where clause should work in order to that.但也当我通过truefalse where 子句应该起作用时。

Error:错误:

Type of conditional expression cannot be determined because there is no implicit conversion between 'bool?'无法确定条件表达式的类型,因为 'bool?' 之间没有隐式转换and 'System.DBNull'和'System.DBNull'

Stored procedure:存储过程:

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# code: 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;
    }

Calling:调用:

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

You can use the ??你可以使用?? operator to provide an alternative for when the status is null .运算符以在状态为null时提供替代方法。 Like @user2864740 commented, both sides have to be compatible types.就像@user2864740 评论的那样,双方都必须是兼容的类型。 This won't work:这行不通:

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

The left hand value of ?? ??左手值is a bool , but the right hand value is not.bool ,但右手值不是。 So the compiler will complain DBNull.Value cannot be "implicitly cast" to bool .所以编译器会抱怨DBNull.Value不能“隐式转换”为bool To solve this, cast the left hand side to object :要解决此问题,请将左侧投射到object

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

Now ??现在?? will evaluate to an object, which can contain both a bool and a DNull.Value .将评估为一个对象,该对象可以包含boolDNull.Value Applying that to your problem, you get:将其应用于您的问题,您将得到:

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

I have a Nullable project, the above code generates compiler warnings and use this pattern我有一个 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;
}

The compiler knows what to pick so that gets solved without any issue during compile time no matter how many nullable data types I use.编译器知道要选择什么,以便在编译期间无论我使用多少可空数据类型都可以毫无问题地得到解决。

my parameters I declare like this我的参数我这样声明

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

I like to reduce reflection when I can and AddWithValue will cause reflection in MS code and you usually end up with the wrong data type in your parameterised queries when there is no need for it as you know the datatype when you write the code.我喜欢尽可能减少反射,而 AddWithValue 会导致 MS 代码中的反射,并且当您在编写代码时知道数据类型时,您通常会在不需要它时在参数化查询中得到错误的数据类型。

using reflection-based SQLParameter constructors is not too smart as when you do that SQL server will cast it into the proper data type in the execution plan making it a Row-By-Row operation.使用基于反射的 SQLParameter 构造函数并不太聪明,因为当您这样做时,SQL 服务器会将其转换为执行计划中的正确数据类型,使其成为 Row-By-Row 操作。 Particularly bad when using TSQL data types like SmallDatetime, date, TinyInt, CHAR, and VarChar data types as they always come out wrong.使用 TSQL 数据类型(如 SmallDatetime、date、TinyInt、CHAR 和 VarChar 数据类型)时尤其糟糕,因为它们总是出错。

You see this when passing strings as they always get reflected in nvarchar(max) compare an indexed email field with a nvarchar(max) parameter... have a look at implicit conversions , we know the data type it needs, the few extra characters we need to type in our program code are worth the hassle when "they say" that the "database is to slow" when it starts bigger than the tiny developer database that probably fits in memory.您在传递字符串时会看到这一点,因为它们总是反映在 nvarchar(max) 中,将索引的电子邮件字段与 nvarchar(max) 参数进行比较......看看隐式转换,我们知道它需要的数据类型,几个额外的字符我们需要输入我们的程序代码是值得的,当“他们说”“数据库很慢”时,当它开始比可能适合内存的微型开发人员数据库大时。

Just because you can make a 1 liner in your code doesn't make it performant仅仅因为您可以在代码中制作 1 行并不能使其具有高性能

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM