简化命令子项的linq表达式

时间:2018-02-17 10:51:52

标签: c# linq

我正在尝试编写一个LINQ查询,该查询获取Course个实体及其映射的Skill子项列表。它们与具有相应CourseIdSkillId的联接表相关联。我希望使用Skill属性对Weight个孩子进行排序,然后对SkillId属性进行排序。我使用的是dot net core 2.0。

在查看有关如何在此处对子实体列表进行排序/排序的类似问题之后:

我想出了这个:

// Create query to get all courses with their skills
var coursesWithUnorderedSkills= db.Courses
    .Include(i => i.Skills)
    .ThenInclude(i => i.Skill);

// Order the skills for each course
await coursesWithUnorderedSkills.ForEachAsync(x => x.Skills = x.Skills
                                   .OrderBy(o => o.Weight)
                                   .ThenBy(o => o.SkillId)
                                   .ToList());

// Get a list of courses from the query
var coursesWithOrderedSkills = await q.ToListAsync();

如何将此简化为单个查询,并且由于我在ToList调用中呼叫ForEachAsync,此查询是否会出现任何意外的性能问题?

模型

public class Course
{
    [Key]
    public int Id { get; set; }
    public List<CourseSkill> Skills { get; set; }
}

public class CourseSkill
{
    public Course Course { get; set; }
    public int CourseId { get; set; }

    public Skill Skill { get; set; }
    public int SkillId { get; set; }

    public int Weight { get; set; } = 0;
}

public class Skill
{
    [Key]
    public int Id { get; set; }
}

1 个答案:

答案 0 :(得分:1)

对于评论感到抱歉,现在有了这个模型,我看起来很清楚你在寻找什么。你是对的,第二个声明将对技能列表进行排序。

无论如何,如果你想对子集合进行排序而不冒险通过IQueryable对数据库进行两次调用,你可以先异步获取课程列表,然后在内存中对技能进行排序:

// Create the list with all courses with their skills
var coursesWithSkills= await db.Courses
    .Include(i => i.Skills)
    .ThenInclude(i => i.Skill)
    .ToListAsync();

// Order the skills for each course once data is in memory
foreach(x in coursesWithSkills)
{
    x.Skills = x.Skills.OrderBy(o => o.Weight)
                       .ThenBy(o => o.SkillId)
                       .ToList());
}

如果你需要那个排序部分不阻塞当前线程,你应该使用Task.Run而不是异步操作来运行它,因为所有的排序工作都是CPU密集型的并且将完成在记忆中。但是我不会进行早期优化,我会保留foreach块,直到你看到任何性能问题。