问题描述
这是我的代码:
string queryString = "Marco".ToLower();
utenti = db.User.Where(p =>
queryString.Contains(p.Nickname.ToLower()) ||
queryString.Contains(p.Nome.ToLower()) ||
queryString.Contains(p.Cognome.ToLower())).ToList();
但我明白了:
String.Contains 方法只支持可以在客户端计算的参数.
Only arguments that can be evaluated on the client are supported for the String.Contains method.
为什么?我不能使用 .Contains()
吗?
Why? Can't I use .Contains()
?
推荐答案
试试 .IndexOf
.不是 LINQ 不能做 Contains
,而是 LINQ to Entities 和 LINQ to SQL 不能.
Try .IndexOf
. It is not LINQ that can't do Contains
, it's LINQ to Entities and LINQ to SQL that can't.
string queryString = "Marco";
utenti = db.User.Where(p =>
queryString.IndexOf(p.Nickname, StringComparison.OrdinalIgnoreCase) >= 0 ||
queryString.IndexOf(p.Nome, StringComparison.OrdinalIgnoreCase) >= 0 ||
queryString.IndexOf(p.Cognom, StringComparison.OrdinalIgnoreCasee) >= 0)
.ToList();
为什么?
LINQ 使用延迟执行.这意味着它会等到您想要迭代查询结果,然后再执行任何操作.LINQ 有 3 种主要类型:
LINQ uses deferred execution. This means it waits until you want to iterate over your query results before it does anything. There are 3 main types of LINQ:
- LINQ to Objects - 当您的
IEnumerable
已经在堆上时. - LINQ to Entities - 当您想使用实体框架查询数据库时.
- LINQ to SQL - 当您想使用 LINQ to SQL 查询数据库时.
在第二个 2 的上下文中延迟执行意味着您的查询不会在数据库上执行,直到您在 foreach
块中枚举结果,或调用像 .ToList 这样的枚举方法
、.ToArray
等.在此之前,您的查询只是作为表达式树存储在内存中.
Deferred execution in the context of the second 2 means that your query is not executed on the database until you enumerate the results in a foreach
block, or invoke an enumeration method like .ToList
, .ToArray
, etc. Until then, your query is just stored as expression trees in memory.
如果 db.User
是内存中的一个集合,那么您的查询将正常工作.但是,当数据位于数据库中时,LINQ to Entities(或 LINQ to SQL)必须将您的表达式树转换为它所谓的存储表达式"——这只是将我的 LINQ 表达式转换为 SQL"的花哨说法.
Your query would work just peachy if db.User
was a collection in memory. However when the data is in a database, LINQ to Entities (or LINQ to SQL) must translate your expression trees to what it calls a "store expression" -- which is just fancy talk for "convert my LINQ expressions to SQL".
现在假设您有一个想要用于查询的自定义 C# 算法,并且您执行了以下操作:
Now imagine you had a custom C# algorithm you wanted to use for your query, and you did something like this:
var result = db.User.Where(x => MyCustomMethod(x));
今天,LINQ to Entities 无法将您的 C# 代码转换为 SQL 查询(存储表达式).这与您每天依赖的许多其他 C# 方法相同.它也不支持 .ToLower
、.ToUpper
、.StartsWith
、.EndsWith
等.有一个可转换为存储表达式的 C# 方法数量有限,而 .IndexOf
恰好是其中之一.
There is no way today that LINQ to Entities can convert your C# code into a SQL query (store expression). It is the same with a lot of other C# methods you rely on daily. It also does not support .ToLower
, .ToUpper
, .StartsWith
, .EndsWith
, etc. There is a limited number of C# methods that can be converted to store expressions, and .IndexOf
just happens to be one of them.
但是请记住,只有我们在这里讨论的字符串对象的 Contains
方法不支持 store 表达式.LINQ to Entities 在 IEnumerable
上支持 .Contains
.以下内容有效并且适用于 LINQ to Entities(不确定 LINQ to SQL):
However keep in mind that it is only the string object's Contains
method that we are talking about here that is not supported for store expressions. LINQ to Entities does support .Contains
on IEnumerable
s. The following is valid and will work with LINQ to Entities (not sure about LINQ to SQL):
var idsIWantToFind = new[] { 1, 2, 3 };
var users = db.Where(x => idsIWantToFind.Contains(x.UserId));
以上相当于做一个 SQL WHERE UserId IN (1, 2, 3)
谓词.
The above is the equivalent of doing a SQL WHERE UserId IN (1, 2, 3)
predicate.
这篇关于LINQ 不能使用 string.contains?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!