使用 Dapper 将参数传递给 SQL 校验和函数
Pass param into SQL checksum function with Dapper
遇到奇怪的问题:
string sql = $@"SELECT * FROM SearchLogs
WHERE CHECKSUM(@query) = cs_SearchTerm
AND Website = @website";
return await Connection.QueryFirstOrDefaultAsync<SearchLog>(sql,
param: new { query, website });
记录 100% 存在于数据库中,但我得到 null
。 cs_SearchTerm
是 computed, int, nullable
字段。然后我试了:
DECLARE @term nvarchar(500)
SET @term = @query
SELECT * FROM SearchLogs
WHERE CHECKSUM(@term) = cs_SearchTerm AND Website = @website
但得到了相同的结果。然后我尝试拆分成两个操作:
private async Task<int> SqlCheckSumAsync(string query)
{
string sql = @"SELECT CHECKSUM(@query)";
return await Connection.ExecuteScalarAsync<int>(sql, param: new { query }, transaction: Transaction);
}
string sql = $@"SELECT * FROM Search_Master
WHERE cs_SearchTerm = @checksum
AND Website = @website";
int checksum = await SqlCheckSumAsync(query);
return (await Connection.QueryFirstOrDefaultAsync<Search_Master>(sql,
param: new { checksum, website },
transaction: Transaction));
但仍然没有得到积极的结果。我想知道我做错了什么?为什么我不能将参数传递给 SQL scalar
?
根据评论,这有效:
SELECT * FROM SearchLogs WHERE cs_SearchTerm = CHECKSUM('abc') AND Website = 'ICF'
所以:这告诉我您使用 varchar
输入计算了校验和。这非常重要,因为 CHECKSUM('abc')
给出了 与 CHECKSUM(N'abc')
完全不同的 答案:
select checksum('abc') as [Ansi], checksum(N'abc') as [Unicode]
给出:
Ansi Unicode
----------- -----------
34400 1132495864
默认情况下,dapper 使用 nvarchar
(因为 .NET 字符串是 utf-16)。所以我们需要告诉 dapper 将其作为 ANSI 字符串传递;幸运的是这很简单:
return await Connection.ExecuteScalarAsync<int>(sql,
new { query = new DbString { Value = query, IsAnsi = true} },
transaction: Transaction);
Dapper 的 DbString
类型允许对字符串的发送方式进行细粒度控制,包括它们是 unicode 还是 ANSI,以及它们是固定宽度(如果是的话:什么)或可变宽度。
遇到奇怪的问题:
string sql = $@"SELECT * FROM SearchLogs
WHERE CHECKSUM(@query) = cs_SearchTerm
AND Website = @website";
return await Connection.QueryFirstOrDefaultAsync<SearchLog>(sql,
param: new { query, website });
记录 100% 存在于数据库中,但我得到 null
。 cs_SearchTerm
是 computed, int, nullable
字段。然后我试了:
DECLARE @term nvarchar(500)
SET @term = @query
SELECT * FROM SearchLogs
WHERE CHECKSUM(@term) = cs_SearchTerm AND Website = @website
但得到了相同的结果。然后我尝试拆分成两个操作:
private async Task<int> SqlCheckSumAsync(string query)
{
string sql = @"SELECT CHECKSUM(@query)";
return await Connection.ExecuteScalarAsync<int>(sql, param: new { query }, transaction: Transaction);
}
string sql = $@"SELECT * FROM Search_Master
WHERE cs_SearchTerm = @checksum
AND Website = @website";
int checksum = await SqlCheckSumAsync(query);
return (await Connection.QueryFirstOrDefaultAsync<Search_Master>(sql,
param: new { checksum, website },
transaction: Transaction));
但仍然没有得到积极的结果。我想知道我做错了什么?为什么我不能将参数传递给 SQL scalar
?
根据评论,这有效:
SELECT * FROM SearchLogs WHERE cs_SearchTerm = CHECKSUM('abc') AND Website = 'ICF'
所以:这告诉我您使用 varchar
输入计算了校验和。这非常重要,因为 CHECKSUM('abc')
给出了 与 CHECKSUM(N'abc')
完全不同的 答案:
select checksum('abc') as [Ansi], checksum(N'abc') as [Unicode]
给出:
Ansi Unicode
----------- -----------
34400 1132495864
默认情况下,dapper 使用 nvarchar
(因为 .NET 字符串是 utf-16)。所以我们需要告诉 dapper 将其作为 ANSI 字符串传递;幸运的是这很简单:
return await Connection.ExecuteScalarAsync<int>(sql,
new { query = new DbString { Value = query, IsAnsi = true} },
transaction: Transaction);
Dapper 的 DbString
类型允许对字符串的发送方式进行细粒度控制,包括它们是 unicode 还是 ANSI,以及它们是固定宽度(如果是的话:什么)或可变宽度。