尝试在 DynamicParameter 中传递 null 时,Dapper 在参数名称附近报告无效语法

Dapper reporting invalid syntax near parameter name when attempting to pass null in a DynamicParameter

我正在尝试从 table 中获取所有记录,其中某个字段不是空字符串或 null。由于我构建查询的方式,ISNULLCOALESCE 不是此处的选项。更改数据库的模式也不是一个选项。

这是我正在 运行 尝试检索记录的代码。

using System;
using System.Data.SqlClient;
using System.Linq;
using Dapper;

namespace DapperMCVE
{
    internal class UserFinder
    {
        public static void Main(string[] args)
        {
            using (var connection = new SqlConnection(@"Data Source=(LocalDB)\MSSQLLocalDB;Integrated Security=True"))
            {
                connection.Execute(@"IF NOT EXISTS(SELECT * FROM sys.tables WHERE name = 'Users')
                                        CREATE TABLE Users(NullableUserId varchar(50) NULL) ON [PRIMARY]");
                connection.Execute(@"DELETE Users");
                connection.Execute(@"INSERT INTO Users(NullableUserId) 
                                     VALUES(''), (NULL), ('SteveSmith@fake.com'), ('Morgan@totallyreal.org')");
                var parameters = new DynamicParameters();
                parameters.Add("UserIdNull", (string)null);
                parameters.Add("UserIdBlank", "");
                try
                {
                    var users = connection.Query(@"SELECT * 
                                                   FROM Users 
                                                   WHERE NullableUserId IS NOT @UserIdNull 
                                                     AND NullableUserId != @UserIdBlank", parameters);
                    Console.WriteLine(users.ToList());
                }
                catch (SqlException e)
                {
                    Console.WriteLine(e);
                }
                Console.ReadKey();
            }
        }
    }
}

抛出的错误是System.Data.SqlClient.SqlException (0x80131904): Incorrect syntax near '@UserIdNull'.

我的假设是上面的代码应该复制这个查询:

SELECT *
  FROM Users
  WHERE NullableUserId IS NOT NULL
    AND NullableUserId != ''

但它似乎在做一些更接近

的事情
SELECT *
FROM Users
WHERE NullableUserId IS NOT 'NULL'
  AND NullableUserId != ''

如果我将查询更改为

SELECT *
FROM Users
WHERE ISNULL(NullableUserId, '') != ISNULL(@UserIdNull, '')

它工作正常。不幸的是,在这种情况下我不能使用 ISNULL

我已经在 SQL Server 2014 和 2016 中复制了它。我们在生产环境中使用 2016。

探查器报告正在执行以下命令 运行:

exec sp_executesql N'SELECT * 
                     FROM Users 
                     WHERE NullableUserId IS NOT @UserIdNull 
                       AND NullableUserId != @UserIdBlank',N'@UserIdNull nvarchar(4000),@UserIdBlank nvarchar(4000)',@UserIdNull=NULL,@UserIdBlank=N''

这让我怀疑这可能是 SQL 服务器本身的问题?

我尝试过的事情(无济于事):

您不能使用 IS NOT 和变量。如果您总是期望 null,则可以对 NullableUserId IS NOT NULL 进行硬编码。 或者使用一些字符串连接创建查询文本

您不能在 sp_executesql 或其他任何地方使用 IS NOT 和参数。
看看这个例子。

此查询 returns 4 条记录来自我的 table :

exec sp_executesql 
N'SELECT * FROM tblUser WHERE gsm IS NOT null AND gsm != '''''

所以现在我尝试使用两个值的参数,现在我得到一个错误

exec sp_executesql 
N'SELECT * FROM tblUser WHERE gsm IS NOT @UserIdNull AND gsm <> @UserIdBlank',
N'@UserIdNull nvarchar(100),@UserIdBlank nvarchar(100)',
@UserIdNull=NULL,@UserIdBlank=N''

但现在我收到错误

Incorrect syntax near '@UserIdNull'

如果没有 sp_executesql

也会出现同样的错误
declare @UserIdNull nvarchar(100) = null
declare @UserIdBlank nvarchar(100) = ''
SELECT * FROM tblUser WHERE gsm IS NOT @UserIdNull AND gsm <> @UserIdBlank

这会产生同样的错误

因此,您唯一的选择是构建不带 IS NOT 值参数的查询或使用 ISNULL()

在您在问题中构建的查询中,您知道何时编写 IS NOT 然后后跟参数。
我建议简单地写 IS NOT NULL 而不是在那里使用参数

IS NOT @UserIdNull 确实是无效的 SQL 语法.... IS NOT NULL 很好。这不是一个小问题 - 这只是一个 SQL 功能:你需要写合法的 SQL.

My assumption is that the above code should replicate this query:

没有。它使用 参数 。语法被保留。 Dapper 不注入文字。这是非常慎重和正确的。 I wrote about this yesterday,正好。