【发布时间】:2021-11-10 08:06:37
【问题描述】:
我已经接管了一些 C# 代码。
代码正在使用一些使用参数的SQL 访问数据库。
所有字符串参数都输入为DbType.AnsiString,而不是DbType.String。
为什么要使用DbType.AnsiString 而不是DbType.String?
【问题讨论】:
我已经接管了一些 C# 代码。
代码正在使用一些使用参数的SQL 访问数据库。
所有字符串参数都输入为DbType.AnsiString,而不是DbType.String。
为什么要使用DbType.AnsiString 而不是DbType.String?
【问题讨论】:
AnsiString
可变长度的非 Unicode 字符流,范围在 1 到 8,000 个字符之间。
字符串
表示 Unicode 字符串的类型。
在数据库中:
nchar 和 nvarchar 是 unicode
char 和 varchar 是非 unicode
【讨论】:
DbType.AnsiString 是DbType.String 的子集吗?
您将使用 ansistring 而不是 string 以避免 SQL Server 数据库中的隐式转换。
即当您将字符串变量传递给 MSSQL 时,它显示为 nvarchar(max)。鉴于 MSSQL 中设计良好的数据库默认情况下可能使用 varchars 而不是 nvarchars(除非有非拉丁字符集的业务需求)。
在这种情况下,字符串变量将导致数据库中的隐式转换。这会导致引擎无法使用某些索引并执行全表扫描(数据库性能万恶之源之一)
【讨论】:
为什么要使用 DbType.AnsiString 而不是 DbType.String?
简答:当您的SqlParameter 指向varchar(或char)数据库列时,您将使用DbType.AnsiString。当您指向nvarchar 列时,请使用DbType.String,因为它的Unicode。
更长的答案:
如果这些映射不准确(例如,将DbType.String 指向varchar(nn) 列,您将在查询计划中看到CONVERT_IMPLICIT 警告,如Pinal Dave 所述:https://blog.sqlauthority.com/2018/06/11/sql-server-how-to-fix-convert_implicit-warnings/
就我而言SqlParameter.Size 属性似乎也很重要:要完全消除CONVERT_IMPLICIT 警告,我必须正确映射DbType 和 Size .默认的Size 如果省略则“根据指定参数值的实际大小推断”(1),这通常会与实际列大小定义不匹配,并且也会引发警告。
【讨论】:
Size 时,我没有收到 CONVERT_IMPLICIT 警告。虽然我没有尝试传递比最大数据库列长度更长的字符串。
了解如何使用 Dapper 在 C# 中解决问题:
SqlMapper.AddTypeMap(typeof(string), DbType.AnsiString);
SqlMapper.AddTypeMap(typeof(String), DbType.AnsiString);
【讨论】: