14

I have a many-to-many relationship defined like so:

Employees
--------------
EmployeeID (PK)

Roles
--------------
RoleID (PK)

EmployeeRoles
--------------
EmployeeID (PK, FK)
RoleID (PK, FK)

I'm trying to get a list of Employees, given a list or RoleIDs:

private MyDBEntities _entities;

public SqlEmployeesRepository(MyDBEntities entities)
{            
    _entities = entities;
}

public IQueryable<Employee> GetEmployeesForRoles(int[] roleIds)
{
    // get employees
}

But if I try and do _entities.EmployeeRoles, there is no EmployeeRoles object. My edmx looks like this:

enter image description here

So it's recognizing the relationship between the two tables, but it's not creating an entity object for EmployeeRoles.

How can I get a distinct list of Employees given a list of role id's?

Steven
  • 18,761
  • 70
  • 194
  • 296

2 Answers2

32

The relationship between the tables Role and Employee is represented as a navigation property - each Employees property in the Role entity will only contain the Employees that have this particular role.

Putting it the other way round - every Employee's Roles property only contains the roles that particular employee has.

Given a set of roles roleIds to look for you can use this to get the list of employees that have a role within that set:

public IQueryable<Employee> GetEmployeesForRoles(int[] roleIds)
{
    var employees = _entities.Employees
                             .Where( x=> x.Roles.Any(r => roleIds.Contains(r.RoleID)))
   return employees;
}

Edit:

The other way to get the employees is to attack the problem from the other side of the relationship (starting with the role, not the employee). This is most likely not as efficient as the first approach, since we have to de-duplicate employees (otherwise employees with i.e. two roles would show up twice):

public IQueryable<Employee> GetEmployeesForRoles(int[] roleIds)
{
    var employees = _entities.Roles
                             .Where( r => roleIds.Contains(r.RoleID))
                             .SelectMany( x=> x.Employees)
                             .Distinct()
   return employees;
}
BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
  • Lol, I was just going to post this as an alternative to your first solution (with `Distinct` etc.), but now it's no alternative anymore. Can you leave your first solution as another option in your answer. It was an interesting way, or was something wrong with it? – Slauma Sep 08 '11 at 19:45
  • @Slauma: Yes it is an alternative - but this seemed more straight-forward after looking at the problem for so I scratched the first approach - let me dig it up again ;-) – BrokenGlass Sep 08 '11 at 20:01
3

Maybe?

var results = from r in db.Roles
              where roleIds.Contains(r.Id)
              select r.Employees;
Kenneth J
  • 4,846
  • 11
  • 39
  • 56