I could reproduce exactly the behavior that you are describing. What I got is:
context.Entry(student) .Collection(s => s.Courses) .Query() .Include(c => c.Students) .Where(c => c.Id == 1) .Load();
I donโt know why we should also be forced to load the other side of the many-to-many relationship ( Include(...) ) when we want to load only one collection. For me, it really seems like an error if I did not miss the hidden reason for this requirement, which is registered somewhere or not.
Edit
Another result: your original request (without inclusion) ...
context.Entry(student) .Collection(s => s.Courses) .Query() .Where(c => c.Id == 1) .Load();
... actually loads the courses into a DbContext like ...
var localCollection = context.Courses.Local;
... shows. A course with Id 1 is indeed in this collection, which means: loading into context. But this is not in the child collection of the student object.
Edit 2
Perhaps this is not a mistake.
First of all: we use two different versions of Load :
DbCollectionEntry<TEntity, TElement>.Load()
Intellisense says:
Loads a collection of objects from the database. Note that objects that already exist in the context are not overwritten with values โโfrom the database.
For another version ( IQueryable extension IQueryable ) ...
DbExtensions.Load(this IQueryable source);
... Intellisense says:
Enumerates the query so that for server queries, such as System.Data.Entity.DbSet, System.Data.Objects.ObjectSet, System.Data.Objects.ObjectQuery, and other query results will be loaded into the associated System.Data.Entity. DbContext, System.Data.Objects.ObjectContext or another cache on the client. This is equivalent to calling ToList, and then dropping the list without the overhead of the list.
So, in this version it is not guaranteed that the child collection is populated only so that the objects are loaded into the context.
The question remains: why does it receive the Presentations collection, and not the Courses collection. And I think the answer is this: because of Relationship> .
A relationship sector is a function in EF that automatically captures relationships between objects that are in the context or that simply load into the context. But this does not happen for all types of relationships. This only happens if the multiplicity is 0 or 1 at one end.
In our example, this means: when we load Presentations into a context (according to our filtered explicit request), EF also loads the Presentation entites foreign key into the Student object - transparently, which means that regardless of whether the FK is set as a property in no model. This loaded FK allows EF to recognize that the loaded Presentations belongs to the Student entity, which is already in context.
But this is not the case for the Courses collection. The course does not have a foreign key for the Student object. Between them there is a many, many, connection table. Thus, when loading Courses EF does not recognize that these courses belong to Student , which is in context, and therefore does not commit the navigation collection to the Student object.
EF does this automatic fix only for links (not collections) for performance reasons:
To fix the relationship, EF transparently rewrites the request so that the relationship information for all relations that has a multiplicity of 0..1 or1 on the other end; in other words, the navigation properties, which are the Help entity. If an enterprise has a relationship with a multiplicity greater than 1, EF will not return the relationship information because it can be successful in performance and compared to involving one foreigner along with the rest of the record. Bringing relationship information means getting all the foreign keys that have been written.
Quote from page 128 of Zeeshan Hirani in the EF detailed guide .
It is based on EF 4 and ObjectContext, but I think it still works in EF 4.1, since DbContext is basically a wrapper around ObjectContext.
Unfortunately, this is a rather complex material to consider when using Load .
And another Edit
So, what can we do when we want to explicitly load one filtered side of the many-to-many relationship? Perhaps only this:
student.Courses = context.Entry(student) .Collection(s => s.Courses) .Query() .Where(c => c.Id == 1) .ToList();