【问题标题】:LINQ query nested list?LINQ查询嵌套列表?
【发布时间】:2021-06-12 06:53:24
【问题描述】:

我不知道如何表达这个问题,但我有一个名为 Teacher 的模型,一个名为 Class 的模型,以及第三个用于 TeacherClasses 的多对多关系的查找表

public class TeacherClass
{
  public int Id get/set
  public int TeacherId get/set
  public int ClassId get/set
}



public class TeacherClassDto
  {

      public int Id get/set
      public int TeacherId get/set
      public int ClassId get/set
      public string ClassName get/set
  }

我想查询老师,并返回一个新的 dto,如下所示:

public class TeacherDto 
{
  ... some props
  public ICollection<Classes> Classes get/set
}

我的 LINQ 查询没有通过。有什么帮助吗?

try
{
    var teachersWithTheirClasses= dbContext.Teachers.Where(x => x.Status == StatusEnum.Active).Select(teacherDto => new TeacherDto
   {
       Id = teacherDto.Id,
       Classes= dbContext.TeacherClasses.Where(x => x.TeacherId == teacherDto.Id).Select(class => new TeacherClassDto
       {
         Id = class.Id,
         ClassId = class .ClassId,
         ClassName = dbContext.Classes.Where(x => x.Id == class.ClassId).Select(x => x.Name)
          }).FirstOrDefault()
});
    return await teachersWithTheirClasses.ToListAsync();
}

错误是无法将 System.IQueryable 隐式转换为字符串(对于 className 属性)

【问题讨论】:

  • 你说的没有通过是什么意思?所以它卡在某个地方?或者它甚至不运行(通过设置断点验证)?
  • 我的查询抛出 500 并说无法翻译。以可翻译的形式重写查询,或通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用显式切换到客户端评估。请参阅go.microsoft.com/fwlink/?linkid=2101038 了解更多信息。
  • 实际上我认为您的查询甚至没有编译(在设计时)。加入条件写错了(顺序错误),class.Id 在哪里?我看不到class 参考(实际上class 是一个特殊的关键字,不能这样写)。这意味着您没有发布您的确切代码。

标签: .net linq asp.net-core


【解决方案1】:

我假设您在表之间没有关系并且您想依赖连接,因此您可以尝试以下查询:

public async Task<List<TeacherDto>> GetTeachers()
    {
       try
       {
          var query = from teacher in dbContext.Teachers
                               join teacherclasses in dbContext.TeacherClasses on teacherclasses.TeacherId equals teacher .Id
                               join classes in dbContext.Classes on classes.Id equals teacherclasses.ClassId
                               where req.Status == StatusEnum.Active
                               select new TeacherDto
                               {
                                   ///stuff
                                   Classes = classes.ToList()
                               };
    
                    return await query.ToListAsync();
          
                }
                catch (Exception ex)
                {
                    throw new Exception($"Couldn't get: {ex.Message}");
                }
            }

【讨论】:

    【解决方案2】:

    因此,您拥有带有 Teachers 和 Classes 的表,并具有使用联结表 TeacherClasses 实现的简单多对多关系。

    您需要每个教师的一些教师属性,以及他所有类的(某些属性)。

    这个怎么样:

    var teachersAndTheirClasses = dbContext.Teachers.Select(teacher => new TeacherDto
    {
        // Select the Teacher properties that you plan to use
        Id = teacher.Id,
        Name = teacher.Name,
        ...
    
        Classes = dbContext.TeacherClasses
            .Where(teacherClass => teacherClass.TeacherId == teacher.Id)
            .Select(teacherClass => dbContext.Classes
                .Where(class => class.Id == teacherClass.ClassId)
                .Select(class => new Class
                {
                      // Select the class properties that you plan to use
                      Id = class.Id,
                      Location = class.Location,
                      ...
                })
                .FirstOrDefault(),
    });
    

    (你可能不能使用局部变量类,但我想你明白了)

    小步走:

    从教师表中的每个教师中,选择他的 ID 和姓名。此外,从该教师中,选择表 TeacherClasses 中属性 TeacherId 的值等于 Teacher.Id 值的所有记录。

    Classes = dbContext.TeacherClasses
        .Where(teacherClass => teacherClass.TeacherId == teacher.Id)
    

    这个教师有零个或多个这些教师类。这个Teacher的每一个TeacherClass都恰好属于一个匹配的Class,即外键ClassId所指的Class。

    dbContext.Classes.Where(class => class.Id == teacherClass.ClassId)
    

    所以,为了得到这个教师的班级,我们得到这个教师的所有教师班级,以及外键 ClassId 所引用的唯一一个班级。选择所需的类属性。

        Classes = dbContext.TeacherClasses
            .Where(teacherClass => teacherClass.TeacherId == teacher.Id)
            .Select(teacherClass => dbContext.Classes
                .Where(class => class.Id == teacherClass.ClassId)
                .Select(class => new Class
                {
                    ...
                })
    

    最后:我们知道每个teacherClass只有一个主键值等于teacherClass.ClassId的Class,所以我们可以选择第一个:

                .FirstOrDefault(),
    

    【讨论】:

    • 我喜欢这个。我正在尝试,只收到一个波浪形错误:)
    猜你喜欢
    • 1970-01-01
    • 2017-11-29
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多