如何告诉Linq实体使用'Like'进行字符串相等?

时间:2016-09-02 21:15:19

标签: c# sql-server entity-framework linq-to-entities

问题

当我用Linq写实体

context.MyTable.Where(t => t.Name == "Test");

它转换为以下sql:

select * from MyTable where Name = 'Test'

我想在Linq中将表达式写入将转换为:

的实体
select * from MyTable where Name like 'Test'

有没有办法实现这个目标?

注意 - 我也尝试了EqualsCompareTo == 0,但无济于事。

背景故事

我想使用Like而不是=的原因是因为如果您使用=,则会在字符串末尾忽略空格,但如果使用Like您使用Contains/StartsWith/EndsWith(请参阅此问题:Why the SQL Server ignore the empty space at the end automatically?,以及:Linq to Entity comparing strings ignores white spaces)。

编辑:为什么它不是How to do SQL Like % in Linq?

的副本

这个问题要求%,这可以用SqlMethods.Like完成,但这不是同一个问题,我想要完全平等,所以这些对我没有帮助。 虽然使用context.MyTable.Where(t => SqlMethods.Like(t.Name, "Test") ,但这个问题确实看起来很有希望,所以我尝试了

dbWriteTable

但我收到以下错误:

  

{“LINQ to Entities无法识别方法'Boolean Like(System.String,System.String)'方法,并且此方法无法转换为商店表达式。”}

2 个答案:

答案 0 :(得分:4)

这是official

  

SQL Server遵循ANSI / ISO SQL-92规范(第8.2节,一般规则#3),介绍如何将字符串与空格进行比较。

如果你不想要它,那就太麻烦了。

一个不忽略空格的SQL函数是DATALENGTH。幸运的是,我们可以在EF查询中使用此函数,因为它是SqlFunctions中的一个函数。因此,您可以添加额外检查DATALENGTH是否等于搜索字符串的长度:

var searchText = "Test";
var result = context.MyTable
                    .Where(t => t.Name == searchText
                             && SqlFunctions.DataLength(t.Name)
                                  == SqlFunctions.DataLength(searchText))

比较DataLengtht.Name的{​​{1}}是必要的,因为searchText会返回字节数,而不是字符数(Ivan,感谢您的评论)。< / p>

答案 1 :(得分:2)

有趣的是,我写了原始问题的答案,并同意这个边缘案例并不重复。

根据您的查询结果大小,您是否可以运行第二个客户端传递:

var result = iQueryableSource
    .Where(i => i.Field.Contains("Fred"))
    .AsEnumerable()
    .Where(i => i.Field == "Fred");

我同意,如果您的数据集很大,这可能是一个问题。

完全是服务器端的另一种方法是组合StartsWith和EndsWith:

var result = iQueryableSource
        .Where(i => i.Field.StartsWith("Fred"))
        .Where(i => i.Field.EndsWith("Fred");