Hello, I am having trouble creating a complex Linq with multiple joins and left joins.
I have 4 tables, as indicated at the end, what it is used for, to see how I need to send an email about a new answer on a topic. Therefore, I receive all messages from the topic that the user has joined. The same user may due to more than 1 post in each topic. After that, I join UserEmailSetting, which means that the user has refused to receive email notifications. Finally, I need to know if an email has been sent to the user notifying me of a new reply (I donβt want to spam my users if many replies have been made), so if a reply notification has been sent since the last visit the site I donβt want to send another mail. Here is my attempt that works, but I would like to optimize it! The problem is that there can be many results in UserEmailSetting, so I get a lot of results when I get only 1 or 2 back.
here is my attept
var select = (from p in ForumPostRepository.Get() join u in UserRepository.Get() on p.UserId equals u.Id join ues in UsersEmailSettingRepository.Get() on u.Id equals ues.UserId join els in (from _el in EmailLogRepository.Get() where _el.Type == "ReplyToTopic" && _el.Values == topicId orderby _el.Id descending select _el) on u.Id equals els.UserId into emailLogs from el in emailLogs.DefaultIfEmpty() where p.TopicId == forumTopic.Id && ues.ReplyToTopic //&& // We only want people who need notifications //!u.Online // We only want people who are not online orderby p.Id descending, el.Id descending select new { User = u, EmailLog = el }); var result = select.DistinctBy(x => x.User.Id).ToList();
Here are the database classes
public class ForumPost { public int? TopicId { get; set; } public int UserId { get; set; } ... } public class User { public int Id { get; set; } public bool Online { get; set; } public DateTime LastLogin { get; set; } ... } public class UsersEmailSetting { public int UserId { get; set; } public bool ReplyToTopic { get; set; } } public class EmailLog { public int Id { get; set; } public int UserId { get; set; } public string Type { get; set; } public string Values { get; set; } public DateTime Created { get; set; } }
Updata: a slightly more structured layout of what I want linq to be able to do, hope it helps
- Get all posts from ForumPostRepository, where topicId is 13.
- Join UserRepository at ForumPostRepository.UserId = UserRepository.Id
- Now I want to see only users
- Join UsersEmailSettingRepository at UserRepository.Id = UsersEmailSettingRepository.UserId
- Left connection with EmailLogRepository on UserRepository.Id = EmailLogRepository.UserId AND EmailLogRepository.Type = "ReplyToTopic" And EmailLogRepository.Values ββ= "topicId"
- β Now there can be from 0 to * results for this query, I want only the last!
source share