c# – Entity Framework中的奇怪行为Linq中的字符串EndsWith方法

前端之家收集整理的这篇文章主要介绍了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#相关文章