views:

101

answers:

3

I want to get all users that have a specific role to a list of usernames.

Is using .Include to include all the users, and going through the UsersReference the best way to loop through all the users that are associated with the role?

I noticed I could not do a foreach(User user in role.Users) but UsersReference seem to work, but is that how it's supposed to be done? Going through the reference?

using (var context = new MyEntities())
        {
            List<string> users = new List<string>();

            Role role = (from r in context.Roles.Include("Users")
                        where r.RoleName == roleName
                        select r).FirstOrDefault();

            foreach (User user in role.UsersReference)
                users.Add(user.UserName);

            return users.ToArray();
        }
A: 

Try using your original foreach loop with ToList()

foreach(var user in role.Users.ToList()) {...}

ktingle
This causes a third collection to be created where only IEnumerables are required. The `List<string> users`, the result of `.ToArray()` and the result of this `.ToList()`
Sander Rijken
The question was how to loop through all the users not the user names.
ktingle
The question was: <quote>I want to get all users that have a specific role to a list of usernames.</quote> The code provided in the question is returning a `string[]` containing usernames of all users in the specified role. Even if looping through the users would be the assignment, the ToList is unneeded there.
Sander Rijken
+2  A: 

Is it possible that your Role table has a Users property? I would think that it would name the navigation property Users, not UsersReference. I don't use EF, but all the examples I've seen name the property after the table. AFAIK it always implements IEnumerable so you should be able use it in a foreach.

If you have it set up right I think you only need:

using (var context = new MyEntities())
{
    return context.Roles
                  .Where( r => r.RoleName == roleName )
                  .SelectMany( r => r.Users )
                  .Select( u => u.UserName )
                  .ToArray();
}
tvanfosson
The Include method isn't necessary since the related User objects are being accessed inside of an active ObjectContext.
Enrico Campidoglio
@Enrico - thanks, I left it in by mistake (copy/paste).
tvanfosson
A: 

Use the .ToArray() helper instead

using (var context = new MyEntities())
{
    return (from role in context.Roles
            where role.RoleName == roleName
            from user in r.Users
            select user.UserName).ToArray();
}

Note that there's no need for .Include("Users") if you do it this way. Using r.Users in the query causes it to be in one query without the need for including it, because it's used in an active ObjectContext.

One a side note, I'm not sure what the method signature of this method is, but in this case IEnumerable<string> is probably a better fit than string[], because you can adjust the implementation later without creating arrays from other types of collections.

Sander Rijken