Je souhaite effectuer une requête à l'aide de EF
et ma requête ressemble à la suivante
SELECT * FROM AspNetUsers U INNER JOIN UserPlan UP ON U.Id = UP.UserId WHERE UP.IsActive = 1 AND ( PlanId=2 OR (PlanId=3 AND EXISTS(SELECT 1 FROM [Group] WHERE AdminId=U.Id )) )
Comment éviter d'interroger deux fois UserPlans?
en SQL
j'écrirais ce qui suit
var users = MyDbc.AspNetUsers.Where ( d => ( d.UserPlans.Where(m => m.IsActive == 1).FirstOrDefault().PlanId == 2 || (d.UserPlans.Where(m => m.IsActive == 1).FirstOrDefault().PlanId == 3 && d.UserGroups.FirstOrDefault().Group.AdminId == d.Id) ) );
3 Réponses :
Utilisez simplement la syntaxe de requête intégrée:
var users = from user in MyDbc.AspNetUsers from plan in user.UserPlans.Where(m=>m.IsActive == 1) where plan.PlanId == 2 || plan.PlanId == 3 && ...
Elle est plus agile en termes de sélection des variables de temps de requête. Et il est BEAUCOUP plus lisible lorsque votre requête est volumineuse. Pour les requêtes simples, j'utilise toujours des extensions LINQ pures.
PS
Comme @juharr mentionné dans le commentaire, votre requête sera probablement être optimisé par le fournisseur SQL, donc vous êtes bon avec les performances, mais la lisibilité et la résistance aux pannes de votre requête sont en effet médiocres.
Je vais probablement emballer ceci dans une vue ou une procédure stockée (si vous avez besoin d'identifiants dynamiques) et charger cela séparément.
var users = MyDbc.Users.ToList();
puis l'appeler en c # ...
CREATE VIEW Users AS SELECT * FROM AspNetUsers U INNER JOIN UserPlan UP ON U.Id = UP.UserId WHERE UP.IsActive = 1 AND ( PlanId=2 OR (PlanId=3 AND EXISTS(SELECT 1 FROM [Group] WHERE AdminId=U.Id )) ) GO
... comme ça.
Je pense que vous recherchez ceci. Vous pouvez simplement faire les deux vérifications directement dans le premier endroit.
d.UserPlans.Where(m => m.IsActive == 1 && (m.PlanId == 2 || (m.PlandId == 3 && d.UserGroups.FirstOrDefault().Group.AdminId == d.I)))
Toute cette requête Linq sera traduite en une seule requête SQL, vous n'interrogez donc pas vraiment UserPlans deux fois.
Vous pouvez facilement vérifier la requête SQL résultante avec
((System.Data.Entity.Core.Objects.ObjectQuery) query) .ToTrace String ()
J'ai utilisé le profileur pour vérifier la requête et il semble que j'ai deux
instructions apply externes de UserPlans