使用 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% 存在于数据库中,但我得到 nullcs_SearchTermcomputed, 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,以及它们是固定宽度(如果是的话:什么)或可变宽度。