Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linq to sql 在联接中使用IQueryable会导致StackOverflow异常_Linq To Sql - Fatal编程技术网

Linq to sql 在联接中使用IQueryable会导致StackOverflow异常

Linq to sql 在联接中使用IQueryable会导致StackOverflow异常,linq-to-sql,Linq To Sql,有人知道这会导致stackoverflow异常的原因吗: public IQueryable<Category> LoadCategories(bool onlyCatsWithProducts, ...) { var db = new DbDataContext(); var res = db.Categories.AsQueryable(); if (onlyCatsWithProducts) res = from p in db.Pro

有人知道这会导致stackoverflow异常的原因吗:

public IQueryable<Category> LoadCategories(bool onlyCatsWithProducts, ...)
{
    var db = new DbDataContext();
    var res = db.Categories.AsQueryable();

    if (onlyCatsWithProducts)
        res = from p in db.Products
              from c in res
              where p.CategoryID == c.ID
              select c;
    ...
    return res;
}
public IQueryable加载类别(仅限bool-ycatswithproducts,…)
{
var db=new DbDataContext();
var res=db.Categories.AsQueryable();
if(仅适用于ATSWITH产品)
res=从p开始,单位为db.乘积
从c到res
其中p.CategoryID==c.ID
选择c;
...
返回res;
}
更新


更改了示例代码,以明确为什么要分配给变量,然后在以后重新分配它。基本上,这是因为我正在编写一个函数,从数据库返回类别,并引入几个参数(例如,onlyCatsWithProducts),其中每个参数仅在结果集有值时过滤结果集。请注意,这仍然不是我的实际代码,因为我的查询更复杂,我只想显示重现错误所需的最简单查询。

为什么要创建一个变量,然后在赋值中使用该变量直接重新赋值?您的查询可能正在执行某种无限递归,导致出现
StackOverFlowException
。尝试以下方法:

var res = 
  from c in DB.Instance.Categories
  from p in DB.Instance.Products
  where p.CategoryID == c.ID
  select c;
更新:

试试下面的方法。我认为您需要避免在
res
的赋值中使用
res

IQueryable<Category> res;

if (onlyCatsWithProducts)
    res = from p in db.Products
          from c in db.Categories.AsQueryable()
          where p.CategoryID == c.ID
          select c;
IQueryable res;
if(仅适用于ATSWITH产品)
res=从p开始,单位为db.乘积
来自db.Categories.AsQueryable()中的c
其中p.CategoryID==c.ID
选择c;

抱歉,发布后我发现交换订单似乎可以解决问题。我不知道为什么:

var db = new DbDataContext();
var res = db.Categories.AsQueryable();
res = from c in res
      from p in db.Products
      where p.CategoryID == c.ID
      select c;

Michael在回答自己的问题时说,他不知道为什么将他的
的顺序从
调换来解决了他的问题

这样会导致堆栈溢出:

var res = db.Categories.AsQueryable();
res = from p in db.Products
      from c in res
      where p.CategoryID == c.ID
      select c;
像这样没有:

var res = db.Categories.AsQueryable();
res = from c in res
      from p in db.Products
      where p.CategoryID == c.ID
      select c;
原因如下。编译器将上述两个查询转换为以下代码:

var res = db.Categories.AsQueryable();
var q = db.Products
    .SelectMany(p => res, (p, c) => new { p, c })
    .Where(x => x.p.CategoryID == x.c.ID)
    .Select(x => x.c);
这分别是:

var res = db.Categories.AsQueryable();
var q = res
    .SelectMany(c => db.Products, (c, p) => new { c, p })
    .Where(x => x.p.CategoryID == x.c.ID)
    .Select(x => x.c);
第一个包含lambda
p=>res
,它基本上捕获了对
res
变量的引用。由于
res
每次在引用中运行查询时都会重新分配自身的重新分配版本和bang-stack溢出

在第二种情况下,
res
在任何lamdba之外,因此不会捕获引用,只使用原始引用,即
res=db.Categories.AsQueryable()
,并且在执行查询时不会更改

它可能同样易于使用:

var res = from c in db.Categories
          from p in db.Products
          where p.CategoryID == c.ID
          select c;

我希望这有助于澄清正在发生的事情。

这是实际代码吗?如果是这样的话,我猜是有一个拼写错误…什么是v?谢谢你修正了拼写错误。对于这个示例,我只是简化了很多代码,所以不是我的实际代码。您不应该需要
.AsQueryable()
。您可能希望尝试显式地将输出类型设置为基础接口,而不是使用
var
AsQueryable()
。我不确定在这里递归分配表达式树时,这是否能解决堆栈溢出问题。@JimWooley
.AsQueryable()
的目的是因为
db.Categories
的类型是
System.Data.Linq.Table
,稍后我将
System.Data.Linq.DataQuery
类型的查询分配给该变量。我当然可以将变量声明为
IQueryable res=db.Categories但这无助于修复错误。已更改问题以反映变量的用途。您的代码确实可以工作,但我的函数接受了许多参数(而不是像我澄清的示例中那样只有一个参数),这些参数根据传入的内容改变查询,因此在一个查询中完成所有操作将使查询变得更加复杂。如果这是应用的第一个过滤器,我可以这样做,但是我的三个过滤器有复杂的连接,需要这种语法,所以对于所有的排列,有很多if-else语句,这不是很好。