Entity framework handles tables participating in Many to Many relationship in a nice manner. If the junction table (sometimes called bridge table, association table, link table, etc) only consists of the foreign keys and no other columns, then that table is abstracted by EF and the two sides get a navigational property exposing a collection of the other side. If the junction table contains other fields as well (e.g. the table has its own primary key column), then that junction table is included in the model with many-to-one relationships with both the participating tables. This post will present some common LINQ queries involving the many to many relationship tables in both scenarios: when the junction table is abstracted by EF, and when it is exposed.
Consider the following scenario having a many to many relationship between Student and Course:
The generated Entity Model will look something like:
However, if the junction table contains any other field other than the two foreign keys, then EF will create a separate entity for it. E.g. lets assume that the StudentCourseEnrollment table has its own ID and some fields like EnrolledFrom and EnrolledTo, like:
The generated Entity Model for the above tables will look like:
Now, we will see how to write some typical LINQ queries involving the two tables participating in many to many relationship for both cases (with and without the junction table exposed in EF model):
Get students enrolled in a particular course
- For case 1, when there is no junction table, and we have the required CourseID to look for, we may write:
dc.Students.Where(s => s.Courses.Any(c => c.CourseID == courseID)) //or without the Any method from s in dc.Students from c in s.Courses where c.CourseID == courseID select s;
- For case 2, when the junction table is included in the entity model, we may need to write:
dc.Students.Where(s => s.StudentCourseEnrollments.Any(e => e.Course.CourseID == courseID) //or without the any method from s in dc.Students from e in s.StudentCourseEnrollments where e.Course.CourseID == courseID select s;
If the foreign keys are also included in the model (applicable only for EF4), we can also directly refer to the CourseID property in the StudentCourseEnrollment table, like:
dc.Students.Where(s => s.StudentCourseEnrollments.Any(e => e.CourseID == courseID) //or without the any method from s in dc.Students from e in s.StudentCourseEnrollments where e.CourseID == courseID select s;
In the above situations, the Any() method is translated to where exists() expression while the other SelectMany methods are translated to join expression.
However, an interesting twist for such queries is to start our query with the junction table and use navigational properties for filtering and selecting. This leaves us with a more compact query:
dc.StudentCourseEnrollments.Where(e => e.Course.CourseID == courseID).Select(e=>e.Student); //the verbose query from e in s.StudentCourseEnrollments where e.Course.CourseID == courseID select e.Student;
Get students enrolled in any course from a list of courses
Notice that such query will use the Contains methodology that is only available with Entity Framework 4. For similar queries with EF1 (EF3.5) we can use the BuildContainsExpression() extension method described here.
- For case 1, when the bridge table is abstracted by EF, this can be written as:
int[,] courseIDs = new int[,] { 1,2,3 };
var students =
from s in dc.Students
from c in s.Courses
where courseIDs.Contains(c.CourseID)
select s;
//similarly, such query can be written with the any method
var students =
from s in dc.Students
where (
from c in s.Courses
where courseIDs.Contains(c.CourseID)
select c
).Any()
select s;
- For case 2, when the bridge table is included in the entity model, we may write:
int[,] courseIDs = new int[,] { 1,2,3 };
var students =
from s in dc.Students
from e in s.StudentCourseEnrollments
where courseIDs.Contains(e.Course.CourseID)
select s;
//starting with the bridge table
var students =
from e in dc.StudentCourseEnrollments
where courseIDs.Contains(e.Course.CourseID)
select e.Student;
//with the any method
var students =
from s in dc.Students
where (
from e in s.StudentCourseEnrollments
where courseIDs.Contains(e.Course.CourseID)
select e
).Any()
select s;
Get students enrolled in ALL courses from a list of courses
- For case 1, when the bridge table is abstracted by EF, we can write the query as:
int[,] courseIDs = new int[,] { 1,2,3 };
var students =
from s in dc.Students
where
(
from c in s.Courses
where courseIDs.Contains(c.CourseID)
select c
).Count() == courseIDs.Count
select s;
- For case 2, when the bridge table is included in the entity model, we may query as:
int[,] courseIDs = new int[,] { 1,2,3 };
var students =
from s in dc.Students
where
(
from e in s.StudentCourseEnrollments
where courseIDs.Contains(e.Course.CourseID)
select e
).Count() == courseIDs.Count
select s;
Thats’s all. I will include some more queries in case I find interesting. Notice that same queries can be written for LINQ To SQL also. The only difference is that the bridge table is always included in the model, so always we need to refer to case 2 from this discussion.




June 29, 2010 at 8:06 PM
Entity Framework: Queries involving many to many relationship tables « Mehroz’s Experiments…
Thank you for submitting this cool story – Trackback from DotNetShoutout…
June 30, 2010 at 6:06 AM
[...] the original post here: Entity Framework: Queries involving many to many relationship … No [...]
June 30, 2010 at 11:04 AM
To learn .net, C#, Java, J2EE, Silverlight, Visual Basic, Asp .net with advanced concepts, you can visit http://advanceddotnettutorial.blogspot.com
October 30, 2010 at 4:39 AM
this is great ,i love it!
November 3, 2010 at 10:47 PM
What are the “dc” and “s” objects above. I was thinking dc was your context but then you use S in the next line. I’m sure this is a newby question but I’m struggling with this and using it in MVC2.
Thanks,
Greg
November 4, 2010 at 11:26 AM
Nice write up
But how do you save to such a relationship?
November 9, 2010 at 10:03 PM
I’m trying to implement exactly your 1st scenario I have 2 tables that are linked with a junction table. But when I run the project I get all employees returned instead of just from the single department.
var employees = (from employee in projectDB.Employees
from department in projectDB.Departments
where department.DepartmentPK == 2
select employee);
return employees;
Any idea why this would not work? This is in VS 2010 express using the repository method similar to the nerdDiner sample project.
Thanks.
November 11, 2010 at 5:59 PM
Nevermind, I found my mistake:
it is “from c in s.Courses” not “from c in dc.Courses”
or in my case: “department in employee.Departments”
Thanks
January 30, 2011 at 2:13 PM
I’m trying to implement your first scenario but in reverse: I’m looking for all the students NOT enrolled in a particular class.
I have everything written up exactly the same except:
where c.CourseID != courseID
yet it pulls back no resuts. Any help?
February 1, 2011 at 7:02 AM
And how can I update this?
February 1, 2011 at 7:08 AM
Cleyton
you use:
De.SaveChanges();
where De is whatever you named the database entity
February 1, 2011 at 12:31 PM
Hi Mike,
where c.CourseID != courseIDdoesn’t make any sense. You need to query like this(Notice the negation ‘!’ is on Any:Alternatively, you can query your database for students enrolled in a particular course and then use the Except method: http://msdn.microsoft.com/en-us/library/bb907956.aspx
February 1, 2011 at 12:43 PM
Hi Cleyton,
For updating relationships, you might need to remove and then add a new relationship. Have a look here:
http://stackoverflow.com/questions/1175251/entity-framework-many-to-many-crud
Also, for inserting such relationships, have a look at this detailed article by Julie Lerman: http://thedatafarm.com/blog/data-access/inserting-many-to-many-relationships-in-ef-with-or-without-a-join-entity/
March 4, 2011 at 7:19 AM
I am trying something similar to this and cannot figure it out. I will show my lack of knowledge first and say I do not know what Entity Framework is. Looks maybe like a newer version of Access? Anyhow I have 2 simple main tables. 1st is Clients Table with CID(PK), CFirstName, CLastName. 2nd is Skills Table with SkillID(PK) and Skills. The 3rd table is a join table with CID & SkillID. It sounded simple to me in the beginning, but all I want is to return a query/report to tell me which clients have at least X number of selected skills. I work in public service and we need a way to match clients to jobs that come in. So an employer may call and ask for people who have experience with welding, carpentry, and plumbing. I need to return individuals who have at least those 3 skills. Or if the employer just wants welding, I need to pull individuals who at least have the welding skill. Everything I have tried to this point returns results of individuals who match any of the skills and the last thing i tried was a listbox that ended up making me select all of the skills that a client had before they would come up. so if someone had 3 skills and I only asked for one they wouldnt come up.
March 26, 2011 at 3:07 PM
Hi,
I have exactly the same scenario and following Entities:
Customer and Site are two tables where joining table is CustomerSites. All i want is to fetch the list of site for a particular customer which are not yet joined into the CustomerSites entity.
as well as, I want to fetch all the sites which are not yet mapped to a customer in customersites.
regards,
WK
May 23, 2011 at 4:07 PM
Thank You
…
January 1, 2012 at 11:38 AM
[...] addition this is a great post about querying many to many relationships in Entity Framework This entry was posted in Uncategorized. Bookmark the [...]
January 18, 2012 at 10:07 PM
That is like one of the clearest explanations of this I’ve seen. Thanks so much!
March 8, 2012 at 11:17 PM
A quick red
June 20, 2012 at 4:17 AM
Syed Mehroz Alam,
You’re the best with this excellent blog. You make Selects easy.
However, where’s the rest?
You know… the other 3/4, i.e. the CUD part of CRUD?
• Insert /Create/Add?
• Delete/Remove?
• Update/Modify?
…and Left Outer Join for Many-to-Many?
July 4, 2012 at 6:25 AM
Assalamu-alaikum!
Jazakallah..for the scenerio 1..
I thought first that it is some bug in the Model not generating the respective Entity in Text Template and that in the Model itself !
September 11, 2012 at 12:12 PM
[...] L’ho letto qua! Posted in dotNet.Tagged code first, dotNet, entities, entity framework, linq. [...]
February 10, 2013 at 1:30 AM
Superb Article about EF M:M.
Keep it up.
May 21, 2013 at 5:09 AM
Thank you for every other fantastic article. The place else could anyone
get that type of information in such an ideal way of writing?
I’ve a presentation subsequent week, and I am at the search for such info.