LINQ to Entities 无法识别方法“System.String ToString()”方法,并且该方法无法翻译为存储表达式
我正在将一些内容从一台 mysql 服务器迁移到一台 sql 服务器,但我不知道如何使这段代码工作:
using (var context = new Context())
{
...
foreach (var item in collection)
{
IQueryable<entity> pages = from p in context.pages
where p.Serial == item.Key.ToString()
select p;
foreach (var page in pages)
{
DataManager.AddPageToDocument(page, item.Value);
}
}
Console.WriteLine("Done!");
Console.Read();
}
当它进入第二个 foreach (var page in pages)
时,它会抛出例外说:
LINQ to Entities 无法识别方法“System.String” ToString()'方法,并且该方法不能翻译为存储 表达。
有谁知道为什么会发生这种情况?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
只需将字符串保存到临时变量,然后在表达式中使用它:
出现问题是因为
ToString()
并未真正执行,它被转换为 MethodGroup,然后解析并转换为 SQL。由于没有等效的ToString()
,因此表达式失败。注意:
请确保您还查看了 Alex 对稍后添加的
SqlFunctions
帮助器类的回答。在许多情况下,它可以消除对临时变量的需要。Just save the string to a temp variable and then use that in your expression:
The problem arises because
ToString()
isn't really executed, it is turned into a MethodGroup and then parsed and translated to SQL. Since there is noToString()
equivalent, the expression fails.Note:
Make sure you also check out Alex's answer regarding the
SqlFunctions
helper class that was added later. In many cases it can eliminate the need for the temporary variable.正如其他人所回答的那样,这会中断,因为 .ToString 在进入数据库的过程中无法转换为相关 SQL。
但是,Microsoft 提供了 SqlFunctions 类 这是可在此类情况下使用的方法的集合。
对于这种情况,您在此处查找的是 SqlFunctions.StringConvert:
当由于某种原因不希望使用临时变量的解决方案时,这是很好的选择。
与 SqlFunctions 类似,您也有 EntityFunctions(EF6 已被 DbFunctions)提供了一组不同的函数,这些函数也与数据源无关(不限于例如 SQL)。
As others have answered, this breaks because .ToString fails to translate to relevant SQL on the way into the database.
However, Microsoft provides the SqlFunctions class that is a collection of methods that can be used in situations like this.
For this case, what you are looking for here is SqlFunctions.StringConvert:
Good when the solution with temporary variables is not desirable for whatever reasons.
Similar to SqlFunctions you also have the EntityFunctions (with EF6 obsoleted by DbFunctions) that provides a different set of functions that also are data source agnostic (not limited to e.g. SQL).
问题是您在 LINQ to Entities 查询中调用 ToString。这意味着解析器正在尝试将 ToString 调用转换为其等效的 SQL(这是不可能的......因此出现异常)。
您所要做的就是将 ToString 调用移至单独的行:
The problem is that you are calling ToString in a LINQ to Entities query. That means the parser is trying to convert the ToString call into its equivalent SQL (which isn't possible...hence the exception).
All you have to do is move the ToString call to a separate line:
将表转换为
Enumerable
,然后使用内部的ToString()
方法调用 LINQ 方法:但要小心,当您调用
AsEnumerable
或ToList
方法,因为您将在此方法之前请求所有实体的所有数据。在上面的例子中,我通过一个请求读取了所有table_name
行。Cast table to
Enumerable
, then you call LINQ methods with usingToString()
method inside:But be careful, when you calling
AsEnumerable
orToList
methods because you will request all data from all entity before this method. In my case above I read alltable_name
rows by one request.有类似的问题。
通过在实体集合上调用 ToList() 并查询列表来解决这个问题。
如果集合很小,这是一个选择。
希望这有帮助。
Had a similar problem.
Solved it by calling ToList() on the entity collection and querying the list.
If the collection is small this is an option.
Hope this helps.
升级到实体框架版本6.2.0对我有用。
我之前使用的是 6.0.0 版本。
希望这有帮助,
Upgrading to Entity Framework Version 6.2.0 worked for me.
I was previously on Version 6.0.0.
Hope this helps,
像这样更改它应该可以工作:
之所以在声明 LINQ 查询的行中而不是在
foreach
行中抛出异常,是因为延迟执行功能,即 LINQ 查询是在您尝试访问结果之前不会执行。这发生在foreach
中,而不是更早的地方。Change it like this and it should work:
The reason why the exception is not thrown in the line the LINQ query is declared but in the line of the
foreach
is the deferred execution feature, i.e. the LINQ query is not executed until you try to access the result. And this happens in theforeach
and not earlier.如果您确实想在查询中输入
ToString
,您可以编写一个表达式树访问者,用 ToString 的调用.com/a/24124190">调用相应的StringConvert
函数:If you really want to type
ToString
inside your query, you could write an expression tree visitor that rewrites the call toToString
with a call to the appropriateStringConvert
function:在 MVC 中,假设您正在根据您的要求或信息搜索记录。
它工作正常。
In MVC, assume you are searching record(s) based on your requirement or information.
It is working properly.
在这种情况下我得到了同样的错误:
在花费了太多时间调试之后,我发现错误出现在逻辑表达式中。
第一行
search.Contains(log.Id.ToString())
工作正常,但处理 DateTime 对象的最后一行让它惨败:删除有问题的行和问题已解决。
我不完全明白为什么,但似乎 ToString() 是字符串的 LINQ 表达式,但不是实体的 LINQ 表达式。 LINQ for Entities 处理像 SQL 一样的数据库查询,而 SQL 没有 ToString() 的概念。因此,我们不能将 ToString() 放入 .Where() 子句中。
但是第一行是如何工作的呢? SQL 没有 ToString(),而是有 CAST 和 CONVERT,所以到目前为止我最好的猜测是 linq forEntity 在一些简单的情况下使用它。 DateTime 对象并不总是那么简单......
I got the same error in this case:
After spending way too much time debugging, I figured out that error appeared in the logic expression.
The first line
search.Contains(log.Id.ToString())
does work fine, but the last line that deals with a DateTime object made it fail miserably:Remove the problematic line and problem solved.
I do not fully understand why, but it seems as ToString() is a LINQ expression for strings, but not for Entities. LINQ for Entities deals with database queries like SQL, and SQL has no notion of ToString(). As such, we can not throw ToString() into a .Where() clause.
But how then does the first line work? Instead of ToString(), SQL have
CAST
andCONVERT
, so my best guess so far is that linq for entities uses that in some simple cases. DateTime objects are not always found to be so simple...我的问题是该列有一个
'text'
数据类型(由于从 sqlite 迁移)。解决方案:只需将数据类型更改为
'nvarchar()'
并重新生成表即可。然后 Linq 接受字符串比较。
My problem was that I had a
'text'
data type for this column (due to a migration from sqlite).Solution: just change the data type to
'nvarchar()'
and regenerate the table.Then Linq accepts the string comparison.
我正在努力淘汰 Telerik Open Access 并将其替换为 Entity Framework 4.0。我遇到了与 telerik:GridBoundColumn 过滤停止工作相同的问题。
我发现它不仅仅适用于 System.String DataTypes。因此,我找到了这个线程,并通过在 Linq 查询末尾使用
.List()
来解决它,如下所示:I am working on retiring Telerik Open Access and replacing it with Entity Framework 4.0. I came across same issue that telerik:GridBoundColumn filtering stopped working.
I find out that its not working only on
System.String DataTypes
. So I found this thread and solved it by just using.List()
at the end of my Linq query as follows:每当您需要在 LINQ 查询中使用方法调用时,只需将 LINQ to Entity 查询转换为 LINQ to Objects 查询(例如调用 ToArray)即可。
Just turn the LINQ to Entity query into a LINQ to Objects query (e.g. call ToArray) anytime you need to use a method call in your LINQ query.