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
RoleIds 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.