【问题标题】:LINQ to Entities does not recognize the method (Partition/Rownumber)LINQ to Entities 无法识别方法(分区/行号)
【发布时间】:2016-02-13 22:24:06
【问题描述】:

我这辈子都想不通为什么这个查询没有运行

它编译正确,但在运行时尝试执行 .ToList() 时失败,代码后面显示如下错误。

我已经查看了类似的答案,但似乎每个答案都有各自的问题。

我将 Query 拆分为多行以尝试缩小违规代码的范围,它似乎在“// Partition Over and Produce RowCount for each partition”之后在线,但我无法弄清楚。

我借用了 GroupBy/Partition 的逻辑: Row_number over (Partition by xxx) in Linq?

[DataContract(Name = "Checksum")]
public class Checksum
{
    [DataMember(Name = "SortColumn")]
    public DateTime SortColumn { get; set; }
    [DataMember(Name = "Identifier")]
    public string Identifier { get; set; }
    [DataMember(Name = "Seqnum")]
    public int Seqnum { get; set; }
}

public void TestLinQ()
{
    myObjectContext context = new myObjectContext();

    DateTime startDate = new DateTime();

    IQueryable<Signin> iQ = context.Signin;
      iQ = iQ.OrderBy(o => o.LastUpdateTimeStamp);
      iQ = iQ.Where(x=>x.LastUpdateTimeStamp == startDate);

    // Partition Over and Produce RowCount for each partition
    IQueryable<Checksum> iQ2 = iQ.GroupBy(x => x.LastUpdateTimeStamp).Select(g => new { g, count = g.Count() }).SelectMany(t => t.g.Select(b => b).Zip(Enumerable.Range(1, t.count), (j, i) => new Checksum { SortColumn = j.LastUpdateTimeStamp, Identifier = j.SigninId, Seqnum = i }));

    iQ2 = iQ2.Where(x => x.Seqnum < 1000);

    // Build Checksum Code

    List<Checksum> outlist = iQ2.ToList();

    // End Build Checksum Code
}

结果消息:

测试方法 WebRole1.Tests.ContinuationTokenTests.TestLinQ 抛出异常: System.NotSupportedException:LINQ to Entities 无法识别方法 'System.Collections.Generic.IEnumerable'1[WebRole1.Tests.Checksum] Zip[Signin,Int32,Checksum](System.Collections.Generic.IEnumerable'1[iSignRepo. Models.Signin], System.Collections.Generic.IEnumerable'1[System.Int32], System.Func`3[iSignRepo.Models.Signin,System.Int32,WebRole1.Tests.Checksum])' 方法,而这个方法不能被翻译成商店表达式。

【问题讨论】:

  • 看来 EF 提供程序不知道如何将 Zip 转换为 SQL。您可能必须在此之前从数据库中获取数据,以便 Zip 在内存中完成。

标签: c# entity-framework linq


【解决方案1】:

基本上无法将 Zip 转换为 SQL。

您需要做的就是在使用该方法之前执行查询

IQueryable<Checksum> iQ2 = iQ.GroupBy(x => x.LastUpdateTimeStamp)
                             .Select(g => new { g, count = g.Count() })
                             .ToList() // Executes the Query
                             .SelectMany(t => t.g.Select(b => b).Zip(Enumerable.Range(1, t.count), (j, i) => new Checksum { SortColumn = j.LastUpdateTimeStamp, Identifier = j.SigninId, Seqnum = i }));

【讨论】:

  • 哎呀....我想根据 ZIP 的结果来限制数据集。那么如果在.ToList() 的时候查询仍然有150000 条记录,它会将它拉到服务器上,然后代码用下一个查询部分减少它吗?希望这不会太昂贵。我会试试看。谢谢!!
  • 根据您在 .Zip 方法中所做的事情,您或许可以做到。我建议提出一个关于如何将其转换为 EF 友好代码的新问题
  • 是的,我想我必须这样做,运行它需要非常多的时间,当在直接 SQL 中完成时,它在 400 毫秒内完成,而这已经超过 100 秒。
猜你喜欢
  • 1970-01-01
  • 2014-08-09
  • 1970-01-01
  • 2012-04-03
  • 2021-11-06
  • 2012-05-03
相关资源
最近更新 更多