2010-03-16 4 views
2

J'ai une requête qui récupère le "feed" d'un utilisateur qui est essentiellement toute leur activité. Si l'utilisateur est connecté, la requête sera filtrée afin que le flux n'inclue pas seulement toutes les données de l'utilisateur spécifié, mais également ses amis.Clause LINQ inefficace 'ANY'

La structure de base de données comprend une table Actions qui contient l'utilisateur qui a créé l'action et une table UserFriends qui contient n'importe quel appariement d'amis à l'aide d'une colonne FrienderId et FriendeeId mappée à UserIds.

J'ai mis en place ma requête LINQ et ça marche bien de retirer les données que je veux, cependant, j'ai remarqué que la requête est transformée en X nombre de clauses CASE dans le profileur où X est le nombre total d'actions dans le base de données. Ce sera évidemment horrible lorsque la base de données a une base d'utilisateurs plus grande que moi et 3 utilisateurs de test.

est ici la requête SQL que je suis en train de réaliser:

select * from [Action] a 
where a.UserId = 'GUID' 
OR a.UserId in 
    (SELECT FriendeeId from UserFriends uf where uf.FrienderId = 'GUID') 
OR a.UserId in 
    (SELECT FrienderId from UserFriends uf where uf.FriendeeId = 'GUID') 

C'est ce que j'ai actuellement ma requête LINQ.

feed = feed.Where(o => o.User.UserKey == user.UserKey 
     || db.Users.Any(u => u.UserFriends.Any(ufr => ufr.Friender.UserKey == 
              user.UserKey && ufr.isApproved) 
     || db.Users.Any(u2 => u2.UserFriends.Any(ufr => ufr.Friendee.UserKey == 
               user.UserKey && ufr.isApproved) 
    ))); 

Cette requête crée ceci: http://pastebin.com/UQhT90wh

qui apparaît X fois dans la trace de profil, une fois pour chaque action dans le tableau. Qu'est-ce que je fais mal? Y a-t-il un moyen de nettoyer ça?

+0

Pouvez-vous s'il vous plaît afficher aussi le code où 'feed' est défini? –

Répondre

1

Je diviser la requête en deux requêtes,

  1. Trouver tous les amis pour l'utilisateur, sélectionnez les clés de l'utilisateur et les mettre dans une liste.
  2. Filtrer le flux en fonction de la clé d'utilisateur et des touches de celle-ci.

Voici mon coup à elle sans connaître vos itnerfaces et ojbects exact, mais il montre le concept:

var friends = db.UserFriends 
        .Where(x => x.isApproved && (
            x.Friender.UserKey == user.userKey || 
            x.Friendee == user.userKey 
           ) 
        ) 
        .Select(x => x.userKey) 
        .Distinct() 
        .ToList(); 
    feed = feed.Where(x => x.userKey == user.userKey || friends.Contains(x.UserKey));

Cela devrait donner une requête similaire à ce

SELECT ... 
FROM feed 
WHERE userKey == 'userkey1' OR userKey in ('userKey2', 'userKey3', ...) 
+0

Je pense que cela ne compilera pas. Vous devez probablement supprimer le var sur la dernière ligne car 'feed' a déjà été défini dans cette portée. –

+0

PARFAIT! Je l'ai modifié un peu mais cela a réduit le nombre de requêtes exécutées de 65 à 12 - http://pastebin.com/WeZA16d4. Merci! – XVargas