You can use the following (I don't use var
here to make the types explicit):
IQueryable<IEnumerable<int>> query = context.Users
.Where(u => u.UserId == x)
.Select(u => u.Roles.Select(r => r.RoleId));
IEnumerable<int> result = query.Single();
This
- throws an exception if the user with
UserId == x
doesn't exist. (I guess you want that because you are using Single
in your example.)
- returns a collection of
RoleId
s of user x
. The collection can be empty (result.Count() == 0
) if the user isn't in any role.
creates the following SQL for query
(with x == 1
) which only joins User
and UserRoles
table:
SELECT
[Project1].[UserId] AS [UserId],
[Project1].[C1] AS [C1],
[Project1].[RoleId] AS [RoleId]
FROM ( SELECT
[Extent1].[UserId] AS [UserId],
[Extent2].[RoleId] AS [RoleId],
CASE WHEN ([Extent2].[UserId] IS NULL)
THEN CAST(NULL AS int)
ELSE 1
END AS [C1]
FROM [dbo].[Users] AS [Extent1]
LEFT OUTER JOIN [dbo].[UserRoles] AS [Extent2]
ON [Extent1].[UserId] = [Extent2].[UserId]
WHERE 1 = [Extent1].[UserId]
) AS [Project1]
ORDER BY [Project1].[UserId] ASC, [Project1].[C1] ASC
If you don't want to distinguish if the user doesn't exist or exists but has no roles you can get a much simpler SQL with this query:
IQueryable<int> query = context.Users
.Where(u => u.UserId == x)
.SelectMany(u => u.Roles.Select(r => r.RoleId));
IEnumerable<int> result = query.ToList();
This returns an empty collection if the user has no roles or if the user doesn't exist. But the SQL is very simple:
SELECT
[Extent1].[RoleId] AS [RoleId]
FROM [dbo].[UserRoles] AS [Extent1]
WHERE 1 = [Extent1].[UserId]
So, here is no join between tables involved at all and the query only uses the UserRoles
link table.