C#: DbType.String与DbType.AnsiString的区别

28

我接手了一些 C# 代码。

这段代码使用参数连接到数据库,并执行 SQL 查询。

所有的字符串参数类型都被定义为 DbType.AnsiString,而不是 DbType.String

为什么要使用 DbType.AnsiString 而不是 DbType.String

4个回答

43

AnsiString
一个长度可变的非 Unicode 字符流,长度范围在 1 到 8,000 个字符之间。

String
表示 Unicode 字符串的数据类型。

在数据库中:

nchar 和 nvarchar 是 Unicode 编码。

char 和 varchar 是非 Unicode 编码。


为什么有人在数据库中使用非 Unicode 字符串时不使用 AnsiString,这个逻辑让我无法理解。+1 - TomTom
DbType.AnsiStringDbType.String 的子集吗? - Craig Johnston
简述:支持中文、日语、韩语等多语言。 - edze
Unicode可以用不同的编码表示 - 问题是哪一个? - DarkWanderer

16
您可以使用ansistring而不是string来避免在SQL Server数据库中发生隐式转换。
例如,当您将一个字符串变量传递到MSSQL时,它会显示为nvarchar(max)。考虑到在MSSQL中,良好设计的数据库默认使用varchars而不是nvarchars(除非有业务要求需要非拉丁字符集)。
在这种情况下,一个字符串变量将导致数据库中发生隐式转换。这可能会使引擎无法使用某些索引并执行完整表扫描(这是所有db性能问题的根源之一)。

5

为什么要使用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警告,我必须正确地映射DbTypeSize。如果省略默认的Size,“从指定参数值的实际大小推断”(1),这通常与实际列大小定义不匹配,也会引发警告。
  1. https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlparameter.size?view=netframework-4.7.2

当我省略varchar列的“Size”时,我没有收到“CONVERT_IMPLICIT”警告。尽管我没有尝试传递超过最大数据库列长度的字符串。 - Vasiliy Zverev
Vasily,感谢您的反馈。我稍微修改了一下注释,指出大小可能是一个因素(在我的情况下是这样),但并非所有情况都是如此。 - Jeff Mergler

-1

看看如何使用Dapper在C#中解决问题:

SqlMapper.AddTypeMap(typeof(string), DbType.AnsiString);
SqlMapper.AddTypeMap(typeof(String), DbType.AnsiString);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接