anouar.bagari
anouar.bagari

Reputation: 2104

outer join linq

I'm new to Linq to object and have a question about the from clause when used in two contexts:

1) to perform a cross join like the query bellow

  var q1 = from person in people
      from job in jobs
      select new {person, job}

2) to perform an outer join

  var q2 = from person in people
     join pet in pets on person equals pet.Owner into gj
     from subpet in gj
     select new { OwnerName = person.FirstName, PetName = subpet.Name };

does the second from clause acts as a cross join or is it evaluated depending on the context? because q1 will produce people.Count * jobs.Count element but q2 will produce only people.Count

Upvotes: 4

Views: 5243

Answers (3)

Dmitry Polyanitsa
Dmitry Polyanitsa

Reputation: 1093

According to MS documentation, to make the second query the left outer join you should use the DefaultIfEmpty method as seen here. The from clause always evaluates the same way: it returns each element in the sequence, will it be either predefined source, or a context variable.

EDIT: I'll try to explain from the start. At first you inner join (group join, to be specific) the people and the pets. Then you select from the resulting collection (actually the person-pets set) to the new anonymous object, getting the person name (from the gj set element) and the subpet name (for each of the pets in the gj set element). I think the second from does not do crossjoin because it selects from gj, and each person is already a part of gj set element. If you call the gj.DefaultIfEmpty() method in the second from clause, then the person without any pets (with empty pets collection inside the gj set element) will be added to the resulting set. You can read the following articles to understand it better:

Upvotes: 3

svick
svick

Reputation: 244757

From is evaluated based on the context. If it wasn't, you wouldn't be able to use context variables like gj. But if you don't use that context, like in your first query, it behaves the same as a cross join.

You're saying the second query gives you an unexpected number of elements. Maybe you shouldn't focus on that, but on what elements are you getting and how does that differ from what you are expecting.

Upvotes: 0

BrokenGlass
BrokenGlass

Reputation: 160852

join is generally used to correlate the elements of two sequences based on a matching key, so it is typically an inner join, but it does depend on what you define as a match, e.g. the following would produce a cross join:

List<int> A = new List<int> { 1, 2, 3, 4, 5 };
List<int> B = new List<int> { 1, 2, 3, 4, 5 };
var c = (from a in A join b in B on 1 equals 1 select new { a, b }).ToList();

Upvotes: 0

Related Questions