I have a complex LINQ query like
var results = from obj1 in context.ProcessBases
join obj2 in context.InspectorArticles
on obj1.ID equals obj2.ProcessBaseID
join obj3 in context.InspectorSamples
on obj2.ID equals obj3.InspectorArticleID
where obj1.ID == _processBaseID
select new {obj1, obj2, obj3,};
Now this result set will have only ONE ProcessBases, each ProcessBase will have MULTIPLE InspectorArticles and each InspectorArticle will have MULTIPLE InspectorSamples. So when I loop through the result set, I want to loop through each InspectorArticle, and then loop through each InspectorSample that belongs to that InspectorArticle, something like:
foreach (InspectorArticle _iart in results.First().obj2)
{
...
foreach (InspectorSample _isamp in results.First().obj3)
{
...
}
}
But since I’ve called a .First() on my result set obviously I get this exception:
foreach statement cannot operate on variables of type x because x does
not contain a public definition for ‘GetEnumerator’
So how can I loop through each instance of InspectorArticle, and then loop through the number of InspectorSamples for that article?
Thanks.
Since you are joining the records together, this statement is not correct:
What you will actually have after you execute your query is an
IEnumerablewhere each object in theIEnumerablecontains a reference to aProcessBase, anInspectorArticleand anInspectorSample. For example, using the code below in LinqPad will yield anIEnumerablewith the following contents:Code:
Results:
So, if you want to keep the Linq statement as is and loop through it with multiple foreach statements, you’ll need to use something like the code below:
Using this code (and continuing the example from above) should get you the output:
The disadvantage of this approach is that you’re having to enumerate the results list several times. If you know this list will always be small, then that’s not such a big deal. If the list will be very large, then you might want to come up with a better way to return the data.
EDIT
To make the code more efficient, you could group by
InspectorArticle.IDand then create aDictionarykeyed by theID, and containing the originalInspectorArticleand the associatedInspectorSamples.The code above will yield the same results as my first example, but for longer lists of articles and samples will be more efficient since it will only enumerate the entire list once when building the
Dictionary.Please note that I keyed the
Dictionaryoff of theIDproperty because I didn’t supply anIEqualityComparerto theGroupBymethod. If you would rather key by theInspectorArticleobject itself, you would need to make sure that two differentInspectorArticleinstances with the sameIDare viewed as equal, which can be done if you create anIEqualityComparerand pass it into theGroupBymethod.