I'm trying to get data from some tables in one SQL query and fill in a model. Things that are important:
- Count of all blogs
- List of all blogs created by the user
- Count of all interviews
- List of all interviews created by the user
- Count of all candidates assigned to the Candidate role
- List of all candidates created by the user
public ApplicationUserActivitiesVM GetUserActivities(string userId)
{
var result = from dummyRow in new List<string> { "X" }
join blog in _context.Blog.Where(w => w.Activity == true) on 1 equals 1 into bg
join ublog in _context.Blog.Where(w => w.Activity == true && w.AuthorId == userId) on 1 equals 1 into ubg
join interview in _context.CandidateInterview.Where(w => w.Activity == true) on 1 equals 1 into iw
join uinterview in _context.CandidateInterview.Where(w => w.Activity == true && (w.CreatorId == userId || w.InterviewerId == userId)).Include(i => i.Candidate) on 1 equals 1 into uiw
join candidate in _context.UserRoles.Where(w => w.RoleId == "candidate role id") on 1 equals 1 into ce
join ucandidate in _context.Users.Where(w => w.UserCreatorId == userId && w.Activity == true).Include(i => i.CandidateInterviewCandidates).ThenInclude(t => t.Candidate) on 1 equals 1 into uce
select new ApplicationUserActivitiesVM()
{
BlogsCount = bg.Count(),
CandidatesCount = ce.Count(),
InterviewsCount = iw.Count(),
UserBlogsCount = ubg.Count(),
UserInterviewsCount = uiw.Count(),
UserCandidatesCount = uce.Where(w => ce.Any(c => c.UserId == w.Id)).Count(),
UserInterviews = uiw.Select(s => new UserActivityInterview(s)).ToList(),
UserBlogs = ubg.Select(s => new UserActivityBlog(s)).ToList(),
UserCandidates = uce.Where(w => ce.Any(c => c.UserId == w.Id)).Select(s => new UserActivityCandidate(s)).ToList()
};
return result.FirstOrDefault();
}
the last join prepares all users created by the user I pass to the method but I would like to get all users in candidate role that were created by the given userId.
Is it any way to improve my query?
To reach that goal I used Where(w => ce.Any(c => c.UserId == w.Id))
twice in select segment. I think it is not an optimise way.
Any help in optimizing the code will be appreciated.
After reading the comments, I edited the code as follows:
ViewModel that I use on a page:
public class ApplicationUserActivitiesVM
{
public int BlogsCount { get; set; }
public int CandidatesCount { get; set; }
public int InterviewsCount { get; set; }
public IList<UserActivityBlog> UserBlogs { get; set; }
public IList<UserActivityCandidate> UserCandidates { get; set; }
public IList<UserActivityInterview> UserInterviews { get; set; }
public int UserBlogsCount => UserBlogs.Count;
public int UserCandidatesCount => UserCandidates.Count;
public int UserInterviewsCount => UserInterviews.Count;
}
Method that I edited:
public ApplicationUserActivitiesVM GetUserActivities(string userId)
{
var blogsCount = _context.Blog.Where(w => w.Activity == true).Count();
var userBlogs = _context.Blog.Where(w => w.Activity == true && w.AuthorId == userId).Select(s => new UserActivityBlog(s)).ToList();
var interviewsCount = _context.CandidateInterview.Where(w => w.Activity == true).Count();
var userInterviews = _context.CandidateInterview.Where(w => w.Activity == true && (w.CreatorId == userId || w.InterviewerId == userId)).Include(i => i.Candidate).Select(s => new UserActivityInterview(s)).ToList();
var candidates = _context.UserRoles.Where(w => w.RoleId == "candidate role id");
var candidatesCount = candidates.Count();
var userCandidates = _context.Users.Where(w => w.UserCreatorId == userId && w.Activity == true).Where(w => candidates.Any(a => a.UserId == w.Id)).Include(i => i.CandidateInterviewCandidates).ThenInclude(t => t.Candidate).Select(s => new UserActivityCandidate(s)).ToList();
var result = new ApplicationUserActivitiesVM
{
BlogsCount = blogsCount,
UserBlogs = userBlogs,
InterviewsCount = interviewsCount,
UserInterviews = userInterviews,
CandidatesCount = candidatesCount,
UserCandidates = userCandidates
};
return result;
}
In terms of performance, I compared the two methods and discovered that they are nearly identical; however, given the database currently has little data, it may need to be enhanced in the future and compared again.
Please let me know if there is a better way.