LINQ 不能使用 string.contains?
- 作者: e贱人就是矫情
- 来源: 51数据库
- 2022-12-08
问题描述
这是我的代码:
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 IEnumerables. 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.
- C#通过fleck实现wss协议的WebSocket多人Web实时聊天(附源码)
- 团队城市未满足要求:MSBuildTools12.0_x86_Path 存在
- 使用 MSBuild.exe 在发布模式下构建 C# 解决方案
- 当我发布 Web 应用程序时,AfterPublish 脚本不运行
- 构建时 T4 转换的产品仅在下一个构建中使用
- ASP.NET Core Application (.NET Framework) for Windows x64 only error in project.assets.json
- 新的 .csproj 格式 - 如何将整个目录指定为“链接文件"到子目录?
- 如何将条件编译符号(DefineConstants)传递给 msbuild
- MSBuild 支持 Visual Studio 2017 RTM 中的 T4 模板
- NuGet 包还原找不到包,没有源
