Accepted answer

i believe example section from how to: perform left outer joins msdn page is really well explained. let's project it to your example. to quote first paragraph from the page

the first step in producing a left outer join of two collections is to perform an inner join by using a group join. (see how to: perform inner joins (c# programming guide) for an explanation of this process.) in this example, the list of person objects is inner-joined to the list of pet objects based on a person object that matches pet.owner.

so in your case, the first step is to perform an inner join of list of students objects with the list of marks objects based on markid in students object matches markid in marks object. as can be seen in the quote, inner join is being performed using group join. if you check note section in msdn page on how to perform group join, you can see that

each element of the first collection appears in the result set of a group join regardless of whether correlated elements are found in the second collection. in the case where no correlated elements are found, the sequence of correlated elements for that element is empty. the result selector therefore has access to every element of the first collection.

what this means in the context of your example, is that by using into you have group joined results where you have all students objects, and sequence of correlated elements of marks objects (in case there is no matching marks objects, the sequence is going to be empty).

now let's go back to how to: perform left outer joins msdn page, in particular second paragraph

the second step is to include each element of the first (left) collection in the result set even if that element has no matches in the right collection. this is accomplished by calling defaultifempty on each sequence of matching elements from the group join. in this example, defaultifempty is called on each sequence of matching pet objects. the method returns a collection that contains a single, default value if the sequence of matching pet objects is empty for any person object, thereby ensuring that each person object is represented in the result collection.

again, to project this to your example, defaultisempty() is being called on each sequence of matching marks objects. as explained above, the method returns a collection that contains a single, default value if the sequence of matching marks objects is empty for any student object, which ensures each student object will be represented in the resulting collection. as a result what you have is set of elements, that contain all student objects, and matching marks object, or if there is no matching marks object, default value of marks, which in this case is null.


what i can say is that "into marksgroup" stores the result data of your joined tables into a temporary (application based, not database based) resultset (in sql terms: a table, so its a select into)

in the next line, your code then selects from marksgroup the columns with your data (in sql terms: select student, department, software, status, marked from marksgroup

so basically, it's getting your data from the db, then putting it aside to "marksgroup, and in the very next step getting marksgroup back in your fingers to take out the data you want to use in your c# code.

try to get rid of marksgroup, it should be possible (haven't tested ist with your code). it should be something like this:

from st in dbcontext.students where st.departmentid == 17
             join d in dbcontext.departments on st.departmentid equals d.departmentid
             join sv in dbcontext.softwareversions on st.softwareversionid equals sv.softwareversionid
             join stat in dbcontext.statuses on st.statusid equals stat.statusid
             join m in dbcontext.marks on st.markid equals m.markid

             select new
                 student = st.studentname,
                 department = p.departmentname,
                 software = sv.softwareversionname,
                 status = st.statusname,
                 marked = m != null ? m.markname : "-- not marked --"

your second question with 'm' : this should also show a different behaviour without your temporary resultset "marksgroup"

Related Query

More Query from same tag