I have a query that pulls back a user's "feed" which is essentially all of their activity. If the user is logged in the query will be filtered so that the feed not only includes all of the specified user's data, but also any of their friends.
The database structure includes an Actions table that holds the user that created the action and a UserFriends table which holds any pairing of friends using a FrienderId and FriendeeId column which map to UserIds.
I have set up my LINQ query and it works fine to pull back the data I want, however, I noticed that the query gets turned into X number of CASE clauses in profiler where X is the number of total Actions in the database. This will obviously be horrible when the database has a user base larger than just me and 3 test users.
Here's the SQL query I'm trying to achieve:
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')
This is what I currently have as my LINQ query.
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)
)));
This query creates开发者_StackOverflow中文版 this: http://pastebin.com/UQhT90wh
That shows up X times in the profile trace, once for each Action in the table. What am I doing wrong? Is there any way to clean this up?
I would split the query into two queries,
- Find all friends for the user, select their user keys and put them into a list.
- Filter the feed according to the userkey and the keys of her.
Here is my shot at it without knowing your exact itnerfaces and ojbects, but it shows the 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));
This should yield a query similar to this
SELECT ...
FROM feed
WHERE userKey == 'userkey1' OR userKey in ('userKey2', 'userKey3', ...)
精彩评论