在C#中不区分大小写的字符串比较无法工作?

18

根据这个问题的答案:

如何进行不区分大小写的字符串比较?

我想进行一次不使用Compare或ToLower的不区分大小写比较:

var user = db.Users.FirstOrDefault(s => String.Equals(s.Username, username, StringComparison.OrdinalIgnoreCase));

然而,我遇到了一个错误:

调用方法'Boolean Equals(System.String, System.String, System.StringComparison)'时提供的参数数量不正确

我做错了什么?


你已经验证过 username 和 s.Username 是否为字符串类型了吗? - Tilak
1
很确定 L2S 不支持那个特定的方法。如果这是实际可执行的 C# 代码,而不是由查询提供程序翻译的内容,那就没问题了。 - Servy
你为什么要避免使用string.Compare呢? - tsells
@tsells 因为 Equals() 更准确地表示了条件。 - Suncat2000
1个回答

39

使用 StringComparison.OrdinalIgnoreCase 进行字符串比较的方式工作在内存中或者对于 IEnumerable<T> 集合。你试图将其用于 IQueryable<T>,但是你所使用的查询提供程序不理解它。

在 Linq-to-Sql 中,你应该能够像这样使用 SqlMethods.Like(s.UserName, userName)

var user = db.Users.FirstOrDefault(s => SqlMethods.Like(s.UserName, userName));

SqlMethods位于System.Data.Linq.SqlClient命名空间中。

Like方法不区分大小写,因此您应该可以获得预期的结果。

编辑:我尝试了一下,结果收到“LINQ to Entities不识别Boolean Like(System.String,System.String)方法,这个方法无法转换为存储表达式。”的错误消息。

这似乎是EF的已知问题(链接)。

这个对我起作用:

db.Users.FirstOrDefault(
     s => s.Username.Equals(username, StringComparison.OrdinalIgnoreCase)
);
看起来虽然 EF 在将静态的 Equals 翻译成 SQL 时遇到了困难,但将实例的 Equals 翻译成 SQL 却没有问题。这是一个非常好的发现——它使得解决方案易于阅读和高效执行。
您也可以使用使用 ToUpperCase 或者 ToLowerCase 的简单方法,但这可能会防止查询优化器使用索引:
// Warning: this may not perform well.
var user = db.Users.FirstOrDefault(s => s.UserName.ToUpperCase() == userName.ToUpperCase());

1
谢谢。我尝试后出现了“LINQ to Entities不识别方法'Boolean Like(System.String, System.String)',该方法无法转换为存储表达式。” - 有什么想法? - SB2055
1
这对我有效:db.Users.FirstOrDefault(s => s.Username.Equals(username, StringComparison.OrdinalIgnoreCase)); 就选择答案方面我不知道该怎么办 - 随意记录一下,然后我会检查您的? - SB2055
你认为我在评论中发布的解决方案有什么问题吗?我正在寻找一个简单、高效的解决方案,符合最佳实践。 - SB2055
1
@SB2055 你的解决方案是最好的:EF在翻译静态Equals时出现问题有点奇怪,但它可以很好地处理实例Equals,但由于这两个函数是分别处理的,所以一个能够正常工作而另一个会失败是有道理的。 - Sergey Kalinichenko

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