如何在EF中订购实体的子集合

时间:2011-12-09 15:01:46

标签: linq entity-framework

我有以下查询:

public IEnumerable<Team> GetAllTeamsWithMembers(int ownerUserId)
        {
            return _ctx.Teams
                 .Include(x => x.TeamMembers)
                 .Where(x => x.UserId == ownerUserId)
                 .OrderBy(x => x.Name).ToList();

        }

我如何按照他们的名字订购团队,然后让每个团队的所有子成员按照他们的名字排序?

似乎这样做我需要创建一个新的DTO类并使用select。我想使用已经创建的EF实体,在这种情况下,Team具有成员的导航属性。我从我的存储库层返回IEnumerable<Team>

在EF中似乎没有一种简单的方式来订购子集合。有人可以帮忙吗?

4 个答案:

答案 0 :(得分:24)

您可以在加载数据后加载数据并在内存中排序。

IEnumerable<Team> teams = _ctx.Teams
            .Include(x => x.TeamMembers)
            .Include(x => x.TeamMembers.Select(u => u.User))
            .Where(x => x.UserId == ownerUserId)
            .OrderBy(x => x.Name).ToList();

foreach (var team in teams)
{
    team.TeamMembers = team.TeamMembers.OrderBy(m => m.Name);
    foreach (var teamMember in team.TeamMembers)
    {
        teamMember.Users = teamMember.Users.OrderBy(u => u.Name);
    }
}

或者您可以使用预测并使用EF的更改跟踪对您的集合进行排序。 Here is an example过滤包含,但同样适用于订购。

答案 1 :(得分:2)

您可以将您的团队及其团队成员转储为匿名类型(可能不是您想要的),如下所示:

public IEnumerable<Team> GetAllTeamsWithMembers(int ownerUserId)
{
    return (from t in _ctx.Teams
        where t.UserId == ownerUserId
        select new {
            Team = t,
            TeamMembers = t.TeamMembers.OrderBy(m => m.Name)
        }).ToList()
}

然后你可以遍历它们:

foreach(Team team in GetAllTeamsWithMembers(1234))
{
    string teamName = team.Team.Name;
    string firstTeamMemberName = team.TeamMembers.First().Name;
}

更新:对于记录,我的意见是不使用此解决方案,而是在循环中或在渲染/绑定期间对每个集合进行排序。

我删除了第二个解决方案,因为有人指出EF不能选择实体。

答案 2 :(得分:1)

我的解决方案:

     var data = await db.lessonTasks
               .Select(res => new
               {
                   details = res,
                   appos  = res.appos.OrderBy(ap=>ap.dateTime).ToList(),
               })
               .OrderBy(r=>r.appos.First().dateTime)
               .ToListAsync();

答案 3 :(得分:0)

遗憾的是,急切加载(Include)不支持对已加载的子集合进行任何过滤或排序。

但是,正如接受的答案中所述,您可以在每个集合都渴望加载之后对其进行排序。我写了一个扩展方法,该方法可以方便地就地通过子属性对集合进行排序,因此无需重新分配:

public static class Extensions
{
    public static void SortOn<T>(this List<T> enumerable, Expression<Func<T, object>> expression)
    {
        var type = expression.Parameters[0].Type;
        var memberName = ((MemberExpression)((UnaryExpression)expression.Body).Operand).Member.Name;

        enumerable.Sort((x, y) =>
        {
            var first = (IComparable)type.GetProperty(memberName).GetValue(x);
            var second = (IComparable)type.GetProperty(memberName).GetValue(y);
            return first.CompareTo(second);
        });
    }
}

然后对子集合进行排序可以简写为:

foreach (var team in teams)
    team.TeamMembers.SortOn(_ => _.Name);