I have some tables User, UserSite, Site & Company. UserSite being the many to many relationship and Site holding a CompanyId.
I'm having an issue creating a Linq query to select Users with their sites and company details, the part that makes this complicated is that there is a lot of filtering going on. You are able to filter by User, Company and site on the web page.
When searching by site it makes sense to show that site in the results. However if searching by user I just want to take the first site found for that user therefore removing duplicate rows. In T-SQL I'd do a sub join and take the top 1, no problem. However with Linq I am struggling to do this. So much so I am thinking of going back to Store Procs.
The code below brings back multiple rows for the user due to the site join, how can I bring back one row for the user when filtering by site.
var users = from u in _arcContext.Users
join us in _arcContext.UserSites on u.Id equals us.UserId
join s in _arcContext.Sites on us.SiteId equals s.Id
join c in _arcContext.Companies on s.CompanyId equals c.Id
where
(!userSearchParams.UserId.HasValue || u.Id == userSearchParams.UserId) &&
((String.IsNullOrEmpty(userSearchParams.UserText) || userSearchParams.UserId.HasValue) || // User Text
(u.FirstName.StartsWith(userSearchParams.UserText, StringComparison.InvariantCultureIgnoreCase)
|| u.LastName.StartsWith(userSearchParams.UserText, StringComparison.InvariantCultureIgnoreCase)
|| u.Username.StartsWith(userSearchParams.UserText, StringComparison.InvariantCultureIgnoreCase))
) &&
((!userSearchParams.CompanyId.HasValue || c.Id == userSearchParams.CompanyId)) && // Company Id
((String.IsNullOrEmpty(userSearchParams.CompanyText) || userSearchParams.CompanyId.HasValue) || // Company Text
(c.Name.StartsWith(userSearchParams.CompanyText, StringComparison.InvariantCultureIgnoreCase)
|| c.Country.StartsWith(userSearchParams.CompanyText, StringComparison.InvariantCultureIgnoreCase)
|| c.City.StartsWith(userSearchParams.CompanyText, StringComparison.InvariantCultureIgnoreCase))
) &&
((!userSearchParams.SiteId.HasValue || s.Id == userSearchParams.SiteId)) && // Site Id
((String.IsNullOrEmpty(userSearchParams.SiteText) || userSearchParams.SiteId.HasValue) || // Site Text
(s.Name.StartsWith(userSearchParams.SiteText, StringComparison.InvariantCultureIgnoreCase)
|| s.Country.StartsWith(userSearchParams.SiteText, StringComparison.InvariantCultureIgnoreCase)
|| s.City.StartsWith(userSearchParams.SiteText, StringComparison.InvariantCultureIgnoreCase))
)
select new UserToSiteAndCompany()
{
User = u,
Site = s,
Company = c
};
Update 1
var site = (from u in _arcContext.Users
join us in _arcContext.UserSites on u.Id equals us.UserId
join s in _arcContext.Sites on us.SiteId equals s.Id
where
((userSearchParams.SiteId.HasValue ? s.Id == userSearchParams.SiteId : true)) && // Site Id
((String.IsNullOrEmpty(userSearchParams.SiteText) || userSearchParams.SiteId.HasValue) || // Site Text
(s.Name.StartsWith(userSearchParams.SiteText, StringComparison.InvariantCultureIgnoreCase)
|| s.Country.StartsWith(userSearchParams.SiteText, StringComparison.InvariantCultureIgnoreCase)
|| s.City.StartsWith(userSearchParams.SiteText, StringComparison.InvariantCultureIgnoreCase))
)
select new { UserSite = us, Site = s}).Take(1);
var users = from u in _arcContext.Users
join us in _arcContext.UserSites on u.Id equals us.UserId
join s in site on us.SiteId equals s.Site.Id
join c in _arcContext.Companies on s.Site.CompanyId equals c.Id
where
(userSearchParams.UserId.HasValue ? u.Id == userSearchParams.UserId : true) &&
((String.IsNullOrEmpty(userSearchParams.UserText) || userSearchParams.UserId.HasValue) || // User Text
(u.FirstName.StartsWith(userSearchParams.UserText, StringComparison.InvariantCultureIgnoreCase)
|| u.LastName.StartsWith(userSearchParams.UserText, StringComparison.InvariantCultureIgnoreCase)
|| u.Username.StartsWith(userSearchParams.UserText, StringComparison.InvariantCultureIgnoreCase))
) &&
((userSearchParams.CompanyId.HasValue ? c.Id == userSearchParams.CompanyId : true)) && // Company Id
((String.IsNullOrEmpty(userSearchParams.CompanyText) || userSearchParams.CompanyId.HasValue) || // Company Text
(c.Name.StartsWith(userSearchParams.CompanyText, StringComparison.InvariantCultureIgnoreCase)
|| c.Country.StartsWith(userSearchParams.CompanyText, StringComparison.InvariantCultureIgnoreCase)
|| c.City.StartsWith(userSearchParams.CompanyText, StringComparison.InvariantCultureIgnoreCase))
)
select new UserToSiteAndCompany()
{
User = u,
Site = s.Site,
Company = c
};