Tracking of an issue reported in StackOverflow: http://stackoverflow.com/questions/12489749/linq-to-ef-join-throws-index-was-out-of-range-after-upgrade-from-vs2010-to-vs2
There's an easy workaround, but this is a functional regression.
Copying the contents of the original StackOverflow question:
After upgrading from Visual Studio 2010 to 2012 code started throwing "ArgumentOutOfRangeException - Index was out of range. Must be non-negative and less than the size of the collection.Parameter name: index" on Linq queries using Joins.
The following simple example made in LINQPad (using an EF data model) gives me the ArgumentOutOfRangeException:
void Main()
{
var iq1 = Customers.Select(ap => ap.ID);
var iq2 = iq1.Join(Customers.Select(ap => ap.ID),
a => a,
b => b,
(a, b) => new { a });
iq2.Dump();
}
Changing the previous example to return an anonymous object containing both sides of the join doesn't give the ArgumentOutOfRangeException and gives results as expected:
void Main()
{
var iq1 = ActionPlans.Select(ap => ap.ID);
var iq2 = iq1.Join(ActionPlans.Select(ap => ap.ID),
a => a,
b => b,
(a, b) => new { a, b });
iq2.Dump();
}
Ok, so for some reason I had to return both sides of the join, but then I tried the following example using a dummy value instead, that also executed without a problem:
void Main()
{
var iq1 = ActionPlans.Select(ap => ap.ID);
var iq2 = iq1.Join(ActionPlans.Select(ap => ap.ID),
a => a,
b => b,
(a, b) => new { a, x = 1 });
iq2.Dump();
}
Taking the first example and adding a ToList() to the first query also makes it execute without a problem:
void Main()
{
var iq1 = ActionPlans.Select(ap => ap.ID).ToList();
var iq2 = iq1.Join(ActionPlans.Select(ap => ap.ID),
a => a,
b => b,
(a, b) => new { a });
iq2.Dump();
}
Important: Trying the first query on a workstation without the Visual Studio 2012 upgrade works fine!
Can anyone confirm/explain this new "feature"? :-)
After giving this some more investigation, I've come to the conclusion that the problem is the anonymous class I'm returning from the Linq query, I think it isn't allowed anymore to return an anonymous class with only one field in it, I know it isn't needed to wrap the field in an anonymous class but ... as I said this worked before upgrading.
Following example gives me the "ArgumentOutOfRangeException - Index was out of range":
void Main()
{
var iq1 = ActionPlans.Select(ap => ap.ID).ToList();
var iq2 = iq1.Join(ActionPlans.Select(ap => ap.ID),
a => a,
b => b,
(a, b) => new { a });
iq2.Dump();
}
this next example works as expected:
void Main()
{
var iq1 = ActionPlans.Select(ap => ap.ID).ToList();
var iq2 = iq1.Join(ActionPlans.Select(ap => ap.ID),
a => a,
b => b,
(a, b) => a );
iq2.Dump();
}
Comments: Changeset 0eed9c4e9ebe
There's an easy workaround, but this is a functional regression.
Copying the contents of the original StackOverflow question:
After upgrading from Visual Studio 2010 to 2012 code started throwing "ArgumentOutOfRangeException - Index was out of range. Must be non-negative and less than the size of the collection.Parameter name: index" on Linq queries using Joins.
The following simple example made in LINQPad (using an EF data model) gives me the ArgumentOutOfRangeException:
void Main()
{
var iq1 = Customers.Select(ap => ap.ID);
var iq2 = iq1.Join(Customers.Select(ap => ap.ID),
a => a,
b => b,
(a, b) => new { a });
iq2.Dump();
}
Changing the previous example to return an anonymous object containing both sides of the join doesn't give the ArgumentOutOfRangeException and gives results as expected:
void Main()
{
var iq1 = ActionPlans.Select(ap => ap.ID);
var iq2 = iq1.Join(ActionPlans.Select(ap => ap.ID),
a => a,
b => b,
(a, b) => new { a, b });
iq2.Dump();
}
Ok, so for some reason I had to return both sides of the join, but then I tried the following example using a dummy value instead, that also executed without a problem:
void Main()
{
var iq1 = ActionPlans.Select(ap => ap.ID);
var iq2 = iq1.Join(ActionPlans.Select(ap => ap.ID),
a => a,
b => b,
(a, b) => new { a, x = 1 });
iq2.Dump();
}
Taking the first example and adding a ToList() to the first query also makes it execute without a problem:
void Main()
{
var iq1 = ActionPlans.Select(ap => ap.ID).ToList();
var iq2 = iq1.Join(ActionPlans.Select(ap => ap.ID),
a => a,
b => b,
(a, b) => new { a });
iq2.Dump();
}
Important: Trying the first query on a workstation without the Visual Studio 2012 upgrade works fine!
Can anyone confirm/explain this new "feature"? :-)
After giving this some more investigation, I've come to the conclusion that the problem is the anonymous class I'm returning from the Linq query, I think it isn't allowed anymore to return an anonymous class with only one field in it, I know it isn't needed to wrap the field in an anonymous class but ... as I said this worked before upgrading.
Following example gives me the "ArgumentOutOfRangeException - Index was out of range":
void Main()
{
var iq1 = ActionPlans.Select(ap => ap.ID).ToList();
var iq2 = iq1.Join(ActionPlans.Select(ap => ap.ID),
a => a,
b => b,
(a, b) => new { a });
iq2.Dump();
}
this next example works as expected:
void Main()
{
var iq1 = ActionPlans.Select(ap => ap.ID).ToList();
var iq2 = iq1.Join(ActionPlans.Select(ap => ap.ID),
a => a,
b => b,
(a, b) => a );
iq2.Dump();
}
Comments: Changeset 0eed9c4e9ebe