Майкл, отвечая на свой вопрос, сказал, что он понятия не имел, почему замена порядка его from
исправила его проблему.
Подобным образом это вызвало переполнение стека:
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);
Первый содержит лямбду p => res
, которая по существу захватываетссылка на переменную res
.Поскольку res
переназначается при каждом запуске запроса, ссылается на переназначенную версию самого себя и переполнение стека взрыва!
Во втором * res
находится вне любого lamdbas, поэтому ссылка не являетсяt захвачено и используется только исходная ссылка - то есть res = db.Categories.AsQueryable()
, и это не изменится при выполнении запроса.
Вероятно, было бы так же просто использовать:
var res = from c in db.Categories
from p in db.Products
where p.CategoryID == c.ID
select c;
Надеюсь, это поможет прояснить, что происходит.