1

这是我的问题:我有一个类有 2 个相同类类型的列表属性(但对如何填充有一些不同的限制),比方说:

public class Team 
{
    [Key]
    public int IDTeam { get; set; }

    public string TeamName { get; set; }

    public List<Programmer> Members { get; set; }

    public List<Programmer> Leaders { get; set; }

    public LoadLists(MyProjectDBContext db) 
    {
        this.Members = db.Programmers.Where(p => p.IDTeam = this.IDTeam 
                 && (p.Experience == "" || p.Experience == null)).ToList();

        this.Leaders = db.Programmers.Where(p => p.IDTeam = this.IDTeam 
                 && (p.Experience != null && p.Experience != "")).ToList();
    }
}

public class Programmer 
{
    [Key]
    public int IDProgrammer { get; set; }

    [ForeignKey("Team")]
    public int IDTeam { get; set; }
    public virtual Team Team { get; set; }

    public string Name { get; set; }

    public string Experience { get; set; }
}

在某些时候,我需要列出团队的成员和领导者,为此我会假设:

return db.Teams
    .Include(m => m.Members.Where(p => p.Experience == "" || p.Experience == null)
    .Include(l => l.Leaders.Where(p => p.Experience != null && p.Experience != "")
    .OrderBy(t => t.TeamName)
    .ToList();

而且,当然,在这种情况下,我会假设它是错误的(因为它根本不起作用)。关于如何实现这一目标的任何想法?

编辑:为了澄清一点,团队类的 2 个列表属性应根据以下内容填写:

1 - 成员属性 - 应包括所有没有经验的相关程序员(proggramer.Experience == null 或“”);

2 - 领导者属性 - 应包括所有具有任何经验的相关程序员(programmer.Experiente != null 或“”);

编辑 2:这是 MyProjectDbContext 声明:

public class MyProjectDBContext : DbContext
{
    public DbSet<Team> Teams { get; set; }
    public DbSet<Programmer> Programmers { get; set; }
}
4

2 回答 2

1

您在谈论 EntityFramework(Linq 到实体)对吗?如果是这样,Include() 是 Linq To Entities 的一种方法,用于在结果集中包含子关系。我认为您应该将 Where() 放在 Inlcude() 之外。

本主题中,您将找到一些有关如何使用 Include() 方法的示例。

所以我建议首先添加 Include() 以包括关系“成员”和“领导者”,然后应用你的 Where-Statement(可以用一个 Where() 来完成)。

return db.Teams
    .Include("Team.Members")
    .Include("Team.Leaders")
    .Where(t => string.IsNullOrWhitespace(t.Members.Experience) ... )

我不清楚的是您的位置标准和您的用例,因为您正在谈论获取具有领导者和成员的团队列表。可能上面的示例将返回与 Where() 语句匹配的团队列表。您可以查看它并在该循环中列出其成员和领导者 - 如果这是用例的话。

另一种选择是这样的:

return db.Members
    .Where(m => string.IsNullOrWhitespace(m.Experience))
    .GroupBy(m => m.Team)

这将为您提供按团队分组的没有经验的成员列表。您可以循环组(团队)及其成员。如果您只想获得每个团队一次,您可以在最后添加 Distinct(m => m.Team) 。

希望这可以帮助。如果您需要一些更详细的代码示例,这将有助于更好地理解您的需求。所以也许你可以多说几句你对查询的期望。

更新:

只需阅读我们听起来很有趣的编辑。我不认为你可以在一个 Linq-To-Entities 语句中做到这一切。就我个人而言,我会在属性 Members 和 Leaders 的 getter 上执行此操作,这些属性会执行自己的查询(作为只读属性)。为了获得大量数据的性能,我什至会使用数据库本身的 SQL 视图来实现。但这在一定程度上取决于使用“成员”和“领导者”的上下文(高频等)。

更新 2:

使用单个查询来获取包含成员和领导子列表的团队表,我将对“程序员”进行查询,并将它们按团队和经验嵌套。然后,结果是包含组(经验丰富/非经验)的组(=团队)列表,其中包含程序员。然后可以使用三个嵌套的 foreach 语句构建最终表。有关一些分组示例,请参见此处(参见示例“GroupBy - Nested”)。

于 2013-09-04T12:13:50.810 回答
0

每当您获取实体时,它们都将存储在上下文中——无论它们被“选择”在何种形式中。这意味着您可以将团队连同所有必要的相关实体一起获取到匿名类型中,如下所示:

var teams =
    (from team in db.Teams
     select new {
         team,
         relatedProgrammers = team.Programmers.Where(
                                   [query that gets all leaders OR members])
     }).ToList().Select(x => x.team);

看起来我们正在丢弃relatedProgrammers这里的字段,但这些Programmer实体仍在内存中。因此,当您执行此操作时:

foreach (var team in teams) team.LoadLists(db);

...它将填充已经获取的程序员的列表,而无需再次查询数据库(假设db与上面的上下文实例相同)。

注意:我自己没有测试过。它基于此答案中显示的类似技术。

编辑- 实际上,看起来你的“领导者”和“成员”涵盖了与团队相关的所有程序员,所以你应该能够做Teams.Include(t => t.Programmers)然后LoadLists

于 2013-09-04T12:42:41.613 回答