LINQ to Entities无法识别方法'System.String ToString()'方法,并且此方法无法转换为存储表达式

Err*_*Efe 126 c# mysql sql linq

我正在将一些东西从一个mysql服务器迁移到一个sql server但我无法弄清楚如何使这个代码工作:

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();
}
Run Code Online (Sandbox Code Playgroud)

当它进入第二个时foreach (var page in pages)它抛出一个异常说:

LINQ to Entities无法识别方法'System.String ToString()'方法,并且此方法无法转换为存储表达式.

谁知道为什么会这样?

Jos*_*osh 133

只需将字符串保存到临时变量,然后在表达式中使用它:

var strItem = item.Key.ToString();

IQueryable<entity> pages = from p in context.pages
                           where  p.Serial == strItem
                           select p;
Run Code Online (Sandbox Code Playgroud)

问题出现是因为ToString()没有真正执行,它被转换为MethodGroup然后解析并转换为SQL.由于没有ToString()等价物,表达式失败.

注意:

请确保您还查看了Alex关于SqlFunctions稍后添加的助手类的答案.在许多情况下,它可以消除对临时变量的需求.

  • 如果我的ToString()应用于相等的左侧,该怎么办?egpSerial.ToString()= item. (14认同)
  • @Josh:我明白它会失败.我要求的是这种情况的解决方案,因为上述解决方案显然不能在那里应用. (7认同)
  • @dotNET这是ORM面临的一个场景.我认为在这些情况下可以通过`ExecuteQuery`或使用带有`ObjectQuery <T>的实体SQL直接进入直接SQL. (5认同)
  • @dotNet那仍然会失败,因为整个事情变成了一个表达式,实体框架试图变成有效的SQL.有一些方法知道如何处理,但`ToString()`不是其中之一. (3认同)
  • @Josh:我正在努力解决这样一个问题.假设我的OrderNumber列是int,但我的用户希望能够在键入时过滤OrderNumbers列表.如果他在搜索框中键入143,他只想要那些具有OrderNumber LIKE'%143%'的记录.我不需要在OrderNumber列上执行ToString()来实现它吗? (3认同)

Ale*_*lex 66

正如其他人已经回答的那样,这会因为.ToString在进入数据库的途中无法转换为相关的SQL而中断.

但是,Microsoft提供了SqlFunctions类,它是可以在这种情况下使用的方法的集合.

对于这种情况,你在这里寻找的是SqlFunctions.StringConvert:

from p in context.pages
where  p.Serial == SqlFunctions.StringConvert((double)item.Key.Id)
select p;
Run Code Online (Sandbox Code Playgroud)

当具有临时变量的解决方案因任何原因而不可取时是好的.

与SqlFunctions类似,您还拥有EntityFunctions(由DbFunctions废弃的EF6),它提供了一组不同的函数,这些函数也是数据源不可知的(不限于例如SQL).

  • 他们在.NET 4中添加了SqlFunctions类,我只是在学习它?很棒的发现. (4认同)

Jus*_*ner 23

问题是您在LINQ to Entities查询中调用ToString.这意味着解析器正在尝试将ToString调用转换为其等效的SQL(这是不可能的......因此异常).

您所要做的就是将ToString调用移到单独的行:

var keyString = item.Key.ToString();

var pages = from p in context.entities
            where p.Serial == keyString
            select p;
Run Code Online (Sandbox Code Playgroud)


小智 10

有类似的问题.通过调用实体集合上的ToList()并查询列表来解决它.如果集合很小,这是一个选项.

IQueryable<entity> pages = context.pages.ToList().Where(p=>p.serial == item.Key.ToString())
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

  • 请注意,这将从数据库中检索*all*Page实体,并在客户端而不是db上进行过滤...通常不是一件好事. (40认同)
  • 对于包含多个记录的任何表,这个方法都是低效的,这意味着所有表都存在:-).但是,这个答案确实帮助了我今天,因为我正在做一个.Select投影,其中包括toString()所以调用.ToList()之前没有给我带来性能损失并且调用.ToList()允许我使用.ToString()格式化和我的.Select语句...... (3认同)

93R*_*dan 9

升级到实体框架版本 6.2.0对我有用

我以前使用的是 6.0.0 版。

希望这可以帮助,


Dan*_*rth 6

像这样改变它应该工作:

var key = item.Key.ToString();
IQueryable<entity> pages = from p in context.pages
                           where  p.Serial == key
                           select p;
Run Code Online (Sandbox Code Playgroud)

在LINQ查询被声明的行中没有抛出异常的原因foreach是在延迟执行功能的行中,即在您尝试访问结果之前不执行LINQ查询.而这种情况发生在foreach而不是更早.


neu*_*t47 5

将表强制转换为Enumerable,然后使用ToString()内部的方法调用LINQ方法:

    var example = contex.table_name.AsEnumerable()
.Select(x => new {Date = x.date.ToString("M/d/yyyy")...)
Run Code Online (Sandbox Code Playgroud)

但是,在调用AsEnumerableToList方法时要小心,因为在此方法之前,您将要求所有实体提供所有数据。在上面的例子中,我table_name通过一个请求读取了所有行。

  • 通常,这不是一个好选择。.AsEnumerable()将所有数据放入内存中,您可以在此处查看更多信息:http://stackoverflow.com/questions/3311244/understanding-asenumerable-in-linq-to-sql (5认同)