Here is your query using SelectMany, modeled exactly after your example. Same output!
var customerOrders2 = customers.SelectMany(
c => orders.Where(o => o.CustomerId == c.Id),
(c, o) => new { CustomerId = c.Id, OrderDescription = o.Description });
The first argument maps each customer to a collection of orders (completely analagous to the ‘where’ clause you already have).
The second argument transforms each matched pair {(c1, o1), (c1, o2) .. (c3, o9)} into a new type, which I’ve made the same as your example.
So:
- arg1 maps each element in the base collection to another collection.
- arg2 (optional) transforms each pair into a new type
The resulting collection is flat like you’d expect in your original example.
If you were to omit the second argument, you would end up with a collection of all orders the match up to a customer. It’d be just that, a flat collection of Order objects.
Using it takes a lot of getting used to, I still have trouble wrapping my head around it sometimes. 🙁