Hisham Aburass
Hisham Aburass

Reputation: 625

StackOverFlow unhandled error" when using LINQ

I have the following code, it stops executing with "StackOverFlow unhandled error".

var Requests= GetList();// return List of Request objects

IQueryable<Order> pos= Enumerable.Empty<Order>().AsQueryable();
if (Requests != null)
 {
   if (Requests.Count > 0)
      {
       var GeneralReq = Requests.Select(loc => loc.Id).ToList();


pos = db.Order.Where(loc => loc.Deleted == false && GeneralReq.Any(a => a == loc.Id));
//HERE, stop executing with StackOverFlow Error.

      }
 }

the problem exactly in here:

pos = db.Order.Where(loc => loc.Deleted == false && GeneralReq.Any(a => a == loc.Id));

Upvotes: 0

Views: 64

Answers (1)

Steve Py
Steve Py

Reputation: 34783

Without knowing what GetList() does the likely problem is that it is returning far too many records to safely inject IDs into your .Any() expression. EF will want to turn that .Any() into a query like:

WHERE orders.OrderId IN (22, 25, 45, 46, 52, 66, ...)

This generally isn't efficient and there are limits to the # of IDs you can pass in. It's better to resolve these criteria as a join. I'm not certain if this can result in a stack overflow so I don't believe the code sample you have is complete because without a .ToList() or similar expression, the IQueryable<Order> pos expression would not have materialized yet.

I would look at the relationships that you can resolve between Requests and Orders. If the Request entity as a reference to an Order, then you can alter GetList() to return an IQueryable<Request> then to get the orders:

IQueryable<Request> requests = GetList();
IQueryable<Order> orders = requests.Select(x => x.Order);

From there you can .Select() the details of the orders that you want, and materialize the resulting data.

IQueryable<Request> requests = GetList();
List<OrderViewModel> orderVMs = requests.Select(x => new OrderViewModel
{
  OrderId = x.Order.OrderId,
  RequestId = x.RequestId,
  CustomerName = x.Customer.Name,
  OrderNumber = x.Order.OrderNumber,
  // ...
}).ToList();

If GetList() can return a significant # or results then use .Take() and .Skip() rather than .ToList() to paginate your results.

Upvotes: 1

Related Questions