我有一个查询,它会撤回用户的“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显示一次。我究竟做错了什么?有没有办法清理它?
答案 0 :(得分:1)
我会将查询分成两个查询,
以下是我在不知道您确切的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', ...)