2009-07-24 6 views
2

Avec .Net Entity Framework et Linq, j'ai un problème pour trouver le meilleur moyen (c'est-à-dire le plus facile à lire/comprendre) d'implémenter une recherche pour savoir si une collection d'entités contient plusieurs valeurs possibles. Envisagez une implémentation de base d'appartenance/rôles, où l'utilisateur a une collection de rôles.Comment puis-je déterminer si une collection d'entités contient plusieurs valeurs possibles?

Quelle serait la "meilleure" façon de dire "cet utilisateur a-t-il l'un des rôles suivants: role1, role2, ou role3?"

je peux le faire avec 1 rôle de vérifier, comme dans:

if myUser.Roles.Contains(role1) { // do something } 

est-il un moyen simple d'ajouter plus de rôles à cette vérification?

Répondre

2

Si la liste des rôles est connu à la compilation, vous pouvez faire quelque chose comme ceci:

if (myUser.Roles.Count(r => r.Id == role1.Id || r.Id == role2.Id) > 0) 
{ 
    // do something 
} 

Si vous voulez vérifier avec une liste dynamique construit des rôles, il devient plus délicat. Faites-moi savoir si c'est ce dont vous avez besoin.

ÉDITÉ changé Any()-Count() > 0 - j'avais misremembered cette limitation dans L2E contre L2SQL.

+0

.Tout() ne semble pas être valable dans LINQ to Entities .... mais cela ressemble à ce que je suis Chercher à accomplir .... –

2

EDIT: Je viens de faire quelques tests .. intéressant que la perf soit assez identique pour IN vs OR, donc en plus du SQL qui a l'air moche, ils fonctionnent à peu près de la même manière. J'ai modifié ma réponse pour refléter cela.

requêtes de style « IN » ne sont pas un soutien en soi par EF (encore) Je crois que ce que vous essayez d'accomplir a été couvert here

Vous pouvez obtenir des entités correspondant à quelque chose comme ceci:

 var roleNamesToMatch = {"Admin","Manager","Associate"}; 
     var expression = BuildOrExpression<Role, name>(r => r.Name, roleNamesToMatch); 
     var matchingRoles = context.RoleSet.Where(expression); 

sur la base de l'arbre d'expression, EF créeraient SQL qui ressemble à ceci:

select r.ID,r.Name from t_Role where r.Name = 'Admin' OR r.Name = 'Manager' 
OR r.Name = 'Associate' 

au lieu o f ce que l'on devrait normalement attendre

select r.ID,r.Name from t_Role where r.Name in ('Admin','Manager','Associate') 
+0

Il n'y a pas de différence de performance SQL entre IN (...) et une série d'instructions OR. En termes de planification de la requête, ils sont identiques. –

+0

Ouais, vous avez raison ... J'ai édité ma réponse pour refléter cela. –

0
var checkForRoles = new Role[] { Role1, Role2, Role3 }; 

if (myUser.Roles.Any(r => search.Contains(checkForRoles))) { 
    //the user is in one of the roles. 
} 
+1

Le framework d'entité ne supporte pas Contains(), et en tout cas Contains() ne prend pas un tableau ou un IEnumerable comme paramètre - donc je ne suis pas sûr de ce que cela est censé faire. –

+0

Vous avez raison. Je n'étais pas au courant que EF ne supportait pas Contains. Je cherchais un moyen d'avoir une liste dynamique à tester.Je faisais des tests ce matin, EF ne semble pas non plus fonctionner avec Intersect - je suis devenu gâté par L2S. –

+0

La seule façon d'obtenir un comportement de type Contient dans EF consiste à utiliser un ExpressionTree –

1

L'utilisation Count() fera plus de travail que nécessaire. Vous pouvez combiner les contrôles d'identité de rôle avec la méthode Any() pour faire une vérification de l'existence:

if(myUser.Roles.Any(role => role.Id == role1.Id || role.Id == role2.Id) 
{ 
    // ... 
} 
Questions connexes