为什么Code First/EF在原始SQL命令中使用'nvarchar(4000)'来表示字符串?

7

本质上,我有一个包含邮政编码的表格。邮政编码字段被定义为'char(5)'。我正在使用代码优先,因此我在我的ZipCode属性上放置了这些属性:

[Key, Column( Order = 0, TypeName = "nchar"), StringLength(5)]
public string ZipCode { get; set; }

现在,如果我在EF中查询这个:
var zc = db.ZipCodes.FirstOrDefault(zip => zip.ZipCode == "12345");

生成的 SQL 使用 nvarchar(4000) 来注入参数。嗯?这是因为 "12345" 在技术上是一个未知长度的字符串吗?EF 不应该聪明到只在查询该表时使用正确的 "nchar(5)" 吗?
我之所以问,是因为 nvarchar(4000) 查询需要半秒钟,而正确范围的查询更快(读取更少)。
任何帮助/建议将不胜感激。

你在向实体添加属性后,是否删除并重新创建了数据库? - BrokenGlass
这是针对一个现有的数据库,我不允许 Code First 重新生成它。现有的数据库明确为 char(5)。 - Nicholas Head
2个回答

2

1
谢谢你的回答。但我想这仍然没有回答为什么EF会以这种方式工作。生成查询时使用相同的数据类型不是更有效吗? - Nicholas Head
另一个针对基于字符串的数据类型养成的好习惯是始终指定参数的长度。该值应为在使用参数的 SQL 谓词中字段的长度,或最大字符串长度(NVARCHAR 为 4,000,VARCHAR 为 8,000),而不是字符串本身的长度。SQL Server 自动参数化始终假定最大字符串长度... 看起来这告诉我们他们为什么会做出这个决定。我有误解吗? - Robert Horvick
1
我想文章这么说也没关系,但是这两个查询之间的性能肯定是不同的。EF团队选择走一条性能较差的路线真的很奇怪。好吧,我会接受你的答案。 - Nicholas Head

1

你尝试过使用MaxLength属性吗?这篇文章很好地总结了EF如何解释各种数据注释属性。


我会尝试使用MaxLength,谢谢。我之前也在使用StringLength,并且和提问者有同样的问题。谢谢。 - Naomi
MaxLength 对我没有起作用,可能是因为我正在使用 MetaDataClass 设置属性? code public partial class OperatorMetadata { [Column(TypeName = "char")] [StringLength(6)] [MaxLength(6)] public String OpCode { get; set; } - Naomi

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