我有一个User表和一个到多个UserSkills表。我需要能够根据技能搜索用户。此查询会获取所需技能的列表,并搜索具有这些技能的用户。我想根据用户所需技能的数量对用户进行排序。因此,如果用户只有3个所需技能中的1个,那么他将比列出3个所需技能中的3个的用户更进一步。
我从以逗号分隔的正在搜索的技能ID列表开始:
List<short> searchedSkillsRaw = skills.Value.Split(',').Select(i => short.Parse(i)).ToList();
然后我只筛选出可搜索的用户类型:
List<User> users = (from u in db.Users
where
u.Verified == true &&
u.Level > 0 &&
u.Type == 1 &&
(u.UserDetail.City == city.SelectedValue || u.UserDetail.City == null)
select u).ToList();
然后是疯狂的部分:
var fUsers = from u in users
select new
{
u.Id,
u.FirstName,
u.LastName,
u.UserName,
UserPhone = u.UserDetail.Phone,
UserSkills = (from uskills in u.UserSkills
join skillsJoin in configSkills on uskills.SkillId equals skillsJoin.ValueIdInt into tempSkills
from skillsJoin in tempSkills.DefaultIfEmpty()
where uskills.UserId == u.Id
select new
{
SkillId = uskills.SkillId,
SkillName = skillsJoin.Name,
SkillNameFound = searchedSkillsRaw.Contains(uskills.SkillId)
}),
UserSkillsFound = (from uskills in u.UserSkills
where uskills.UserId == u.Id && searchedSkillsRaw.Contains(uskills.SkillId)
select uskills.UserId).Count()
} into userResults
where userResults.UserSkillsFound > 0
orderby userResults.UserSkillsFound descending
select userResults;
这有效!但对我来说,它似乎超级膨胀,效率低下。特别是次要部分,计算发现的技能数量。
感谢您提供任何建议。
- R的
答案 0 :(得分:3)
我认为应该这样做:
(from u in users
where u.UserSkills.Any(skill => searchedSkillsRaw.Contains(skill.SkillId))
select new
{
u.Id,
u.FirstName,
u.LastName,
u.UserName,
UserPhone = u.UserDetail.Phone,
UserSkills = u.UserSkills,
UserSkillsFound = u.UserSkills.Where(skill => searchedSkillsRaw.Contains(skill.SkillId)).Count()
} into userResults
orderby userResults.UserSkillsFound descending
select userResult).ToList();
但是,由于这是一个在SQL服务器上执行的查询,我强烈建议从第一个查询中删除“ToList()”调用。因为这实际上导致LINQ在SQL服务器上运行两个单独的查询。您应该将其更改为IQueryable。 LINQ的强大之处在于可以在几个步骤中构建查询,而无需在两者之间实际执行查询。因此,只有在构造整个查询时才应该调用'ToList'。实际上,您目前所做的是在内存中而不是在数据库服务器上运行第二个查询。
关于您的UserSkills一对多关系,您不需要在LINQ中进行明确的连接。您只需访问集合属性即可。
如果您需要更多解释,请告诉我。
迈克尔
答案 1 :(得分:0)
为什么不让人们这样做,比如fUsers.UserSkills.Count()
?它将首先减少从服务器检索的数据量。
或者,您可以创建一个包含计算字段的视图,然后将其映射到某个类型。将查询倒计数到数据库。