效率低'ANY'LINQ条款

时间:2010-03-16 20:39:53

标签: linq entity-framework ado.net

我有一个查询,它会撤回用户的“Feed”,这实际上就是他们的所有活动。如果用户已登录,则将过滤查询,以便该Feed不仅包括所有指定用户的数据,还包括他们的任何朋友。

数据库结构包括一个Actions表,用于保存创建操作的用户; UserFriends表,用于保存使用映射到UserIds的FrienderId和FriendeeId列的任何朋友配对。

我已经设置了我的LINQ查询,它可以回收我想要的数据,但是,我注意到查询在profiler中变成了X个CASE子句,其中X是数据库中的总动作数。当数据库的用户群不仅仅是我和3个测试用户时,这显然会很糟糕。

这是我想要实现的SQL查询:

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')

这是我目前的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)
      )));

此查询创建此: http://pastebin.com/UQhT90wh

在配置文件跟踪中显示X次,对表中的每个Action显示一次。我究竟做错了什么?有没有办法清理它?

1 个答案:

答案 0 :(得分:1)

我会将查询分成两个查询,

  1. 找到该用户的所有朋友,选择他们的用户密钥并将其放入列表中。
  2. 根据用户密钥和她的密钥过滤Feed。
  3. 以下是我在不知道您确切的itnerfaces和ojbects的情况下拍摄的照片,但它显示了这个概念:

        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));

    这应该产生类似于此

    的查询
    SELECT ... 
    FROM feed 
    WHERE userKey == 'userkey1' OR userKey in ('userKey2', 'userKey3', ...)