1

I need to add a dynamic number of Join operations to a LINQ expression. The number is the size of the DemHeaderIDs array. The Joins include a Where clause with a parameter taken from the DemoHeaderIDs array. Using DemoHeaderIDs[0] in the first set works fine. But when trying to use a DemoHeaderID[i] in a loop I get the error message below.

When I use a hard coded integer instead of DemoHeadersID[i], the code runs fine and the result is correct.

My Code:

private void DoSomething(int[] DemoHeaderIDs, OVContext _context)
{   //first set of joins
    var q = from oh in _context.OrgHierarchy
            join odd in _context.OrgDemoData on oh.Identifier equals odd.Identifier
            join dh in _context.DemoHeader.Where(h => h.DemoHeaderId == DemoHeaderIDs[0]) on odd.Demoheaderid equals dh.DemoHeaderId
            select new
            {
                Name = odd.Demovalue,
                Parent = "All",
                Identifier = oh.Identifier
            };

    for (int i = 1; i < DemoHeaderIDs.Count(); i += 1)
    {   //dynamic joins
        q = from qObj in q
            join odd in _context.OrgDemoData on qObj.Identifier equals odd.Identifier
            join dh in _context.DemoHeader.Where(h => h.DemoHeaderId == DemoHeaderIDs[i]) on odd.Demoheaderid equals dh.DemoHeaderId
            select new
            {
                Name = odd.Demovalue,
                Parent = qObj.Name,
                Identifier = qObj.Identifier
            };
    }

    var ql = q.ToList();

The Error Message:

System.IndexOutOfRangeException: Index was outside the bounds of the array. at lambda_method(Closure ) at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ParameterExtractingExpressionVisitor.Evaluate(Expression expression, String& parameterName)

Adding EnableSensitiveDataLogging() to the DbContext configuration did not add information to the message.

I'm using EntityFramework.Core 2.2.

Tobias Tengler
  • 6,848
  • 4
  • 20
  • 34
GilShalit
  • 6,175
  • 9
  • 47
  • 68
  • 1
    The key is the word "Closure" inside the error message. Check SO for `for` loop close over variable issue. Shortly, inside the body introduce new variable `int index = i;` and use it instead of `i` in query/lambda expressions. – Ivan Stoev Jun 23 '19 at 13:55
  • 3
    this is the classic "I've captured the loop variable" problem... https://stackoverflow.com/questions/271440/captured-variable-in-a-loop-in-c-sharp – Marc Gravell Jun 23 '19 at 14:44

1 Answers1

0

Well that did indeed do the trick:

Added int Index=i;

and then replaced DemoHeadersID[i] with DemoHeadersID[index]

You live and learn.

GilShalit
  • 6,175
  • 9
  • 47
  • 68