微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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(不区分大小写)

原文地址:https://www.jb51.cc/csharp/95065.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐