【问题标题】:Why this Linq code always throws System.StackOverflowException?为什么这个 Linq 代码总是抛出 System.StackOverflowException?
【发布时间】:2009-07-13 14:12:19
【问题描述】:
 //A query to a local object
 var deletionCommands = commands
     .Where(a => a.Operation != Operation.Addition)
     .Select(a => new { a.Prestador.cod_prestador, a.Prestador.cod_desdobramento })
     ;
 //A Linq-To-SQL query
 var toDelete = db.Prestadors
     .Where(a => deletionCommands.Contains(new { a.cod_prestador, a.cod_desdobramento }))
     ;
 db.Prestadors.DeleteAllOnSubmit(toDelete);
 db.SubmitChanges();

唯一解决问题的是显式循环:

 foreach (var command in commands)
 {
    if(command.Operation != Operation.Addition)
    {
        var toDelete = db.Prestadors
            .Where(a =>
                a.cod_prestador == command.Prestador.cod_prestador &&
                a.cod_desdobramento == command.Prestador.cod_desdobramento
            );
        db.Prestadors.DeleteAllOnSubmit(toDelete);
    }
 }
 db.SubmitChanges();

【问题讨论】:

  • 真的是调用 AsEnumerable 引发了异常吗?哎呀-通常这不会做任何重要的事情。那是没有实际迭代它?
  • @Jon,这是一种简化。替换为实际代码。
  • @Jeff 现在我通过显式循环解决了问题,我认为它消除了命令对象的责任
  • @Jader,既然你已经解决了它,你可能不再关心了,但我很好奇:你是否使用相等测试而不是 Contains 方法尝试了你的原始语法?也就是说,您是否尝试过.Where(a => a.cod_prestador == deletionCommands.Prestador.cod_prestador && ... 而不是.Where(a => deletionCommands.Contains(new { a.cod_prestador, a.cod_desdobramento }))
  • @Jeff 不,我没有尝试过,因为我看到“包含”方法等同于“显式循环内的直接比较”。

标签: c# .net linq linq-to-sql stack-overflow


【解决方案1】:

这确实是一个错误,并已在 LINQ 4.0 中得到纠正

http://damieng.com/blog/2009/06/01/linq-to-sql-changes-in-net-40

查询稳定性 包含现在检测自引用 IQueryable 并且不会导致堆栈溢出

编辑 在 .NET 3.5 中解决问题:当使用“自动生成值”= True 时,您必须将“延迟加载”设置为 False - 否则会出现递归错误。

EDIT2上述解决方案无效。

【讨论】:

  • “自动生成值”和“延迟加载”属性在哪里设置?
  • 当您在 Visual Studio 上打开 dbml 时,它会打开一个用于 ORM 的可视化设计器。单击一个字段(在类内)并打开属性窗口。
【解决方案2】:

在最后一行设置断点,然后运行代码。然后当它在断点处停止时,在该代码块的开头添加另一个断点。然后在调试器中继续(跳过)。它应该到达新的断点,您可以检查堆栈以查看它是如何回调自身的。

Operation 属性的实现是什么?也许这会以递归方式回调到其他代码。

【讨论】:

  • 操作没有实现(除了 {get; set;})并且是一个“枚举”
  • 嗯...那么我认为您的下一站将是 Microsoft 支持...您的环境导致低层 Linq To SQL 出现严重错误。
  • 是的,我想是的。如果我可以重现此问题并隔离其他可能的原因,我可以将其报告为错误。
  • 这确实是一个错误,请参阅我的回复
【解决方案3】:

我知道这已经是一篇旧帖子了,但是将 Contains 方法更改为 Equals 也对我有用。

StackOverflowException 失败

Dim iLottery As IEnumerable(Of Lottery) = From lottery2 In combined2 Where Not (From lottery1 In combined Select lottery1.NUMBER).Contains(lottery2.NUMBER) Select lottery2

这不是

Dim iLottery As IEnumerable(Of Lottery) = From lottery2 In combined2 Where Not (From lottery1 In combined Select lottery1.NUMBER).Equals(lottery2.NUMBER) Select lottery2

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-25
    • 2013-11-13
    • 1970-01-01
    相关资源
    最近更新 更多