c# – Entity Framework中的奇怪行为Linq中的字符串EndsWith方法
背景
我有一个表只包含一列:名称. | Name | | test1.com | | test2.com | | test3.com | | test4.com | 问题 如果我查询 var email = "a@test2.com"; Table.Where(x => email.EndsWith(x.Name)); 我会得到一个空的列表.但是如果我首先查询所有行,并计算这样的内存中的位置 var email = "a@test2.com"; Table.ToList().Where(x => email.EndsWith(x.Name)); 我会得到一个仅包含test2.com的列表是正确的. 第一个查询生成的SQL是 SELECT "Extent1"."Name" AS "Name" FROM "USER"."Table" "Extent1" WHERE (( NVL(INSTR(REVERSE(:p__linq__0),REVERSE("Extent1"."Name")),0) ) = 1) 我已经尝试用“a@test2.com”替换:p__linq__0并在SQLDeveloper中运行查询,结果是正确的. 更多信息 如果我将EndsWith()更改为Contains(),问题就会消失.这是生成的SQL for Contains() SELECT "Extent1"."Name" AS "Name" FROM "USER"."Table" "Extent1" WHERE (( NVL(INSTR(:p__linq__0,"Extent1"."Name"),0) ) > 0) 你有什么想法EndsWith或REVERSE方法有什么问题? 环境 > EF5.0 解决方法
这条线关系到我,是使用EF的人的一个常见的陷阱:
Table.ToList().Where(x => email.EndsWith(x.Name)); 部分Table.ToList()是最糟糕的部分,因为这实际上会将整个表格实现到内存中,然后在C#中执行EndsWith. Table.Where(x => email.EndsWith(x.Name)); 我会根据一般原则警告这种方法,因为当桌子增长到合理的大小时,这将是非常缓慢的.在构建查询之前,通过从电子邮件中分离出该域,可以在查询命中数据库之前,尽可能地执行此操作: var email = "a@test2.com"; /* You should null check this of course and not just assume a match was found */ var domain = Regex.Match(email,"@(.*)").Groups[1].Value; /* Note: ToList() materialisation happens at the end */ var result = Table.Where(x => x.Name == domain).ToList(); 此外,如果您需要在存储电子邮件的列的域名上进行匹配,那么我首选的方法是将电子邮件分割,并将域名存储在索引和匹配的单独列中,这将缩放并成为很容易管理.记住,这些天数据是便宜的…特别是与不可索引的表扫描相比. 还要记住(对于两种情况),您的数据库设置为CI(不区分大小写) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |