【问题标题】:LINQ to Entities does not recognize the method 'System.Linq.IQueryable`LINQ to Entities 无法识别方法“System.Linq.IQueryable”
【发布时间】:2013-09-13 14:27:34
【问题描述】:

我想运行这个 LINQ 简单代码以在 LINQ 中记录编号,但结果低于错误

var model = _db2.Persons.Select(
    (x, index) => new 
    {
        rn = index + 1,
        col1 = x.Id
    }).ToList();

错误:

LINQ to Entities 无法识别该方法 'System.Linq.IQueryable1[<>f__AnonymousType22 [System.Int32,System.Int32]] 选择[Person,f__AnonymousType22](System.Linq.IQueryable1 [MvcApplication27.Models.Person],System.Linq.Expressions.Expression1[System.Func3 [MvcApplication27.Models.Person,System.Int32,f__AnonymousType2`2 [System.Int32,System.Int32]]])' 方法,并且这个方法不能翻译成store 表达。

【问题讨论】:

  • 看起来Persons 不是IQueryable,请先尝试使用CastOfType(当然如果它们存在的话)。
  • 不,这是因为索引查找记录号。这是代码优先,当我在 lambda 中删除索引时我没有问题!
  • 作为标题的注释System.Linq.IQueryable 是返回类型,而不是方法名称。您在方括号 ([<>f__AnonymousType22 [System.Int32,System.Int32]]) 中看到的内容是 <int, f__AnonymousType22<>> 中的内容,如果您在哪里输入的话。实际功能在该部分之后Select[Person,<>f_AnonymousType22](...)

标签: c# .net linq entity-framework


【解决方案1】:

问题在于 LINQ to Entities 不了解如何将 Select 重载(为您提供索引的重载)转换为 SQL 查询。您可以通过首先从数据库中选择您需要的部分来解决此问题(以避免不必要地选择每一列),然后执行AsEnumerable() 将其作为IEnumerable<T> 而不是IQueryable<T>,然后执行Select纯粹在 C# 中(简而言之,IQueryable<T>s 被转换为 SQL,而IEnumerable<T>s 在代码中运行)。

var model = _db2.Persons.Select(x => x.Id).AsEnumerable().Select(
    (id, index) => new
    {
        rn = index + 1,
        col1 = id
    }).ToList();

请注意,您所拥有的查询似乎是无序的,因此每次调用它时 id/index 配对都会发生变化。如果您希望保持一致性,您应该按一些东西排序(例如_db2.Persons.OrderBy(...))。

编辑

添加来自Scott的评论:

作为一个很好的参考here is the list of all Linq statements built in to the framework and a listing if it is compatible or not

【讨论】:

  • 作为框架内置的所有 Linq 语句的一个很好的参考 here is the list 以及是否兼容的列表。
  • 你不认为 2 select(select().AsEnumerable().Select()) 与同等简单的 1 语句 SQL 相比会导致效率降低吗?
  • @ehsan 是的,但您不能将 Select<T, int>(...) 函数与实体框架一起使用。您要么需要将Query Syntaxlet 一起使用,要么使用比您现有的更复杂的方法语法(我认为这会大大降低可读性)
  • 补充@ScottChamberlain 所说的,这里最大的性能问题是数据库的I/O。由于我们仅通过选择 Id 将其保持在最低限度,因此此处的性能应该与最佳的 LINQ to Entities 解决方案几乎相同。
【解决方案2】:

您可以只选择 Id,然后使用 linq to objects 创建您自己的匿名对象,例如:

var model = _db2.Persons.Select(x => x.Id)
                        .ToList() // return int[]
                        .Select((id, index) => new
                                {
                                    rn = index + 1,
                                    col1 = id
                                 }) // return anonymous[] (with rn and col1)
                         .AsEnumerable(); // get an IEnumerable (readonly collection)

这可能是因为 Entity Framework 不支持这种使用 linq 的查询,因为 linq 可以在内存中执行,因此,在这种情况下,您可以选择您需要的(id 在您的情况下)并执行它,使用ToList() 方法来具体化您的查询,之后您将在内存中拥有一个列表,因此,您可以使用 linq to objects 并根据需要使用支持的方法。

【讨论】:

  • 中间可以AsEnumerable()。你会少一个List()
  • 如果你能解释一下为什么你需要这样做就好了。 (我试图发布我自己的答案,说类似的话,但我对如何解释为什么会发生在 EF 新手身上感到困惑)
猜你喜欢
  • 1970-01-01
  • 2015-06-21
  • 1970-01-01
  • 2014-08-09
  • 1970-01-01
  • 2012-04-03
  • 2021-11-06
  • 2012-05-03
相关资源
最近更新 更多