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
> .NET4.5
> Oracle11g
> ODP.NET11.2 Release 3

解决方法

这条线关系到我,是使用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(不区分大小写)

相关文章

C#项目进行IIS部署过程中报错及其一般解决方案_c#iis执行语句...
微信扫码登录PC端网站应用的案例(C#)_c# 微信扫码登录
原文地址:http://msdn.microsoft.com/en-us/magazine/cc163...
前言 随着近些年微服务的流行,有越来越多的开发者和团队所采...
最近因为比较忙,好久没有写博客了,这篇主要给大家分享一下...
在多核CPU在今天和不久的将来,计算机将拥有更多的内核,Mic...