C# 尝试在DynamicParameter中传递null时,Dapper报告参数名称附近的无效语法
我试图从某个字段不是空字符串或null的表中获取所有记录。由于我构建查询的方式,C# 尝试在DynamicParameter中传递null时,Dapper报告参数名称附近的无效语法,c#,sql-server,dapper,C#,Sql Server,Dapper,我试图从某个字段不是空字符串或null的表中获取所有记录。由于我构建查询的方式,ISNULL和COALESCE不是这里的选项。更改数据库的架构也不是一个选项 这是我试图检索记录的代码 using System; using System.Data.SqlClient; using System.Linq; using Dapper; namespace DapperMCVE { internal class UserFinder { public static
ISNULL
和COALESCE
不是这里的选项。更改数据库的架构也不是一个选项
这是我试图检索记录的代码
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)“@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 Server本身的问题
我尝试过的事情(无效):
或者使用一些字符串连接创建查询文本您不能在sp_executesql或其他任何地方使用
IS NOT
和参数。看看这个例子 此查询从我的表中返回4条记录:
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''
exec sp_executesql
N‘从tblUser中选择*,其中gsm不是@UserIdNull和gsm@UserIdBlank’,
N'@UserIdNull nvarchar(100),@UserIdBlank nvarchar(100)',
@UserIdNull=NULL,@UserIdBlank=N''
但现在我得到了错误
“@UserIdNull”附近的语法不正确
如果不使用sp_executesql执行此操作,则会出现相同的错误
declare @UserIdNull nvarchar(100) = null
declare @UserIdBlank nvarchar(100) = ''
SELECT * FROM tblUser WHERE gsm IS NOT @UserIdNull AND gsm <> @UserIdBlank
declare@UserIdNull-nvarchar(100)=null
声明@UserIdBlank nvarchar(100)=”
从tblUser中选择*,其中gsm不是@UserIdNull和gsm@UserIdBlank
这会产生相同的错误
因此,您唯一的选择是为is NOT
值或使用ISNULL()
在您在问题中构建的查询中,您知道何时写入不是
,然后后跟一个参数。我建议简单地编写
IS NOT NULL
而不是在那里使用参数IS NOT@UserIdNull
实际上是无效的SQL语法<代码>不为空可以。这不是一个简单的问题——这只是一个SQL特性:您需要编写合法的SQL
我的假设是上述代码应该复制此查询:
SELECT *
FROM Users
WHERE NullableUserId IS NOT NULL
AND NullableUserId != ''
没有。它使用参数。保留语法。Dapper不注入文本。这是非常慎重和正确的,正如它发生的那样。那么,为什么不使用探查器捕获实际的sql命令呢?我不知道是否简洁,但可能在
parameters.Add中(“UserIdNull”,(string)null)
您应该以某种方式使用DBNull.Value?@GuidoG我从分析器中添加了命令。我提供的第二个链接地址是DBNull.Value
。tl;dr是dapper不支持它,因为他们希望您使用null
。为什么在这种情况下不能使用isnull()?@GuidoG我正在根据传递给我的JSON对象动态构建整个查询。我无法提前知道该字段是否可以为空,如果可以,相应的默认值是什么。话虽如此,我可能会修改API以允许这样做,但我希望找到一种解决方案,允许Dapper对空值进行过滤。问题是我事先不知道字段是否可以为空。用户正在传递操作员,在这种情况下,不是
。即使我知道字段是可空的,我也不知道ISNULL
的默认值应该是什么。我明白了,但是当你得到操作符不是时,你能不能不总是在它后面写NULL
,而不是一个参数?不,因为不是可能是不在的一部分,是的,你是对的。恐怕我已经没有选择了,我们不应该期望这里显示的代码(在这个答案中)能够正常工作。sp_executesql
的全部要点——它存在的原因——是允许动态SQL使用参数;参数从不被注入-它们作为参数保留。这在sp_executesql
中不是问题-这是正确的行为。我强烈建议您浏览一下有趣的网站。我不知道SQL中不支持这一点。