2009-09-28 7 views
3

Dire que j'ai la base de données suivante:Linq Combiner gauche associez des données

Users 
------- 
UserId (PK) 
UserName 

Roles 
----- 
RoleId (PK) 
RoleName 

UserRoles 
--------- 
UserId (PK) 
RoleId (PK) 

Utilisateurs 1-M UserRoles M-1 Rôles

Utilisation LinqToSQL, je veux retourner l'ensemble suivant:

[User1], [Role1, Role2, Role3] 
[User2], [Role2, Role3] 
[User3], [] 

Etc ...

Quelle est la manière la plus efficace de créer cette requête LinqToSql?

En outre, si je souhaite créer un filtre pour renvoyer uniquement les utilisateurs possédant le rôle 1, qu'est-ce que cela impliquerait?

Thx.

Répondre

4

Définir "efficace". Mais sinon ...

from u in dataContext.Users 
select new { User = u, Roles = u.UserRoles.Select(ur => ur.Role) } 

et filtrage des utilisateurs par RoleID:

from u in dataContext.Users 
where u.UserRoles.Any(ur => ur.RoleID == 1) 
select u 

ou par un autre attribut Role, par exemple, Name:

from u in dataContext.Users 
where u.UserRoles.Any(ur => ur.Role.Name == "Role 1") 
select u 

En combinant tous ensemble:

from u in dataContext.Users 
select new 
{ 
    User = u, 
    Roles = from ur in u.UserRoles 
      where ur.RoleID == 1 || ur.Role.Name == "Role 1" 
      select ur.Role 
} 
+0

Je ne suis en aucun cas familier avec LINQ to SQL mais je ne suis pas convaincu que ce soit correct. U.UserRoles' ne suggère-t-il pas que 'UserRoles' est un champ de la table User? – Tinister

+1

Pas du tout. L2S crée automatiquement des "propriétés de navigation" de type collection lorsqu'une autre table fait référence à cette table via une clé étrangère. Tant que la table 'UserRole' a' UserID' défini comme table FK à 'User', la classe d'entité générée pour' User' aura une propriété nommée 'UserRoles'. –

+0

Comment filtrer par ID de rôle? – zzz

1

Ceci est la seule requête que je construirait pour obtenir le résultat souhaité toutes en même temps

from u in Users 
join ur in UserRoles on u.UserId equals ur.UserId 
join r in Roles on ur.RoleId equals r.RoleId 
group r by u into grouping 
select grouping 

Il produit l'instruction SQL suivante:

SELECT [t0].[UserId], [t0].[Username] 
FROM [Users] AS [t0] 
INNER JOIN [UserRoles] AS [t1] ON [t0].[UserId] = [t1].[UserId] 
INNER JOIN [Roles] AS [t2] ON [t1].[RoleId] = [t2].[RoleId] 
GROUP BY [t0].[UserID], [t0].[Username] 
GO 

-- Region Parameters 
DECLARE @x1 Int = 2 
-- EndRegion 
SELECT [t2].[RoleId], [t2].[RoleName] 
FROM [Users] AS [t0] 
INNER JOIN [UserRoles] AS [t1] ON [t0].[UserId] = [t1].[UserId] 
INNER JOIN [Roles] AS [t2] ON [t1].[RoleId] = [t2].[RoleId] 
WHERE @x1 = [t0].[UserId] 

@Pavel « s ressemble à elle produit une meilleure SQL déclaration:

SELECT [t0].[UserId], [t0].[Username], [t2].[RoleId], [t2].[RoleName] (
    SELECT COUNT(*) 
    FROM [UserRoles] AS [t3] 
    INNER JOIN [Roles] AS [t4] ON [t4].[RoleId] = [t3].[RoleId] 
    WHERE [t3].[UserId] = [t0].[UserId] 
    ) AS [value] 
FROM [Users] AS [t0] 
LEFT OUTER JOIN ([UserRoles] AS [t1] 
    INNER JOIN [Roles] AS [t2] ON [t2].[RoleId] = [t1].[RoleId]) ON [t1].[UserId] = [t0].[UserId] 
ORDER BY [t0].[UserId], [t1].[UserRoleId], [t2].[RoleId] 

En termes d'efficacité, le test va être le meilleur moyen de déterminer quelle approche la plus performante est pour votre situation.

Questions connexes