【问题标题】:Subqueries in Linq when attempting to get counts尝试获取计数时 Linq 中的子查询
【发布时间】:2020-11-18 12:04:42
【问题描述】:

我正在尝试让一些子查询在我的调用中起作用。我试图让这个调用一次访问数据库,但我一生无法解决如何。查询在 GoodSections 部分中断。我尝试了许多不同的方法来做到这一点。我不断收到这条消息:

无法翻译。要么以可翻译的形式重写查询,要么通过插入对 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync() 的调用显式切换到客户端评估

有人可以帮我吗?

var test = context.UserAssessments.Include(n => n.Assessment).Include(n => n.UserSections).ThenInclude(userSection => userSection.Section)
                .OrderBy(n => n.StartDateTime);

            MyAssessments = await test.Select(assessment => new MyAssessmentVM()
            {
                Assessment = assessment.Assessment.Name,
                CompletedDateTime = assessment.CompletedDateTime,
                StartedDateTime = assessment.StartDateTime,
                UserAssessmentID = assessment.ID,
                GoodSections = assessment.UserSections.Where(userSection => userSection.Section.SectionType != SectionTypeEnum.Reading)
                            .Count(n => n.Percentage < n.Section.ReadinessRangeHigh && n.Percentage > n.Section.ReadinessRangeLow)
            }).ToListAsync();

【问题讨论】:

  • 为什么要将WhereCount 之间的条件分开?我会将整个条件放在后者中。或者,有条件在Where,然后是.ToList().Count()
  • 我将 where 语句分开了,因为我最初将它全部放在 where 语句中并且它不断抛出错误。它分开的唯一原因是我试图测试并弄清楚如何让它工作

标签: linq .net-core


【解决方案1】:

您的代码:

 GoodSections = assessment.UserSections
    .Where(userSection => userSection.Section.SectionType != SectionTypeEnum.Reading)

    // End of Where!

    .Count(n => n.Percentage < n.Section.ReadinessRangeHigh 
             && n.Percentage > n.Section.ReadinessRangeLow)

显然,每个 Assesment 都有一个由零个或多个 UserSection 组成的序列。在我看来,每个 UserSection 都有一个 Percentage 和一个 Section。

您使用 Include 来访问此 Section 的值,因此我假设 Section 在不同的表中,具有一对多关系:每个 Section 都是零个或多个 UserSection 的部分;每个 UserSection 都属于确切的一个 Section,即外键所指的 Section。

首先,尝试简化您的计数,如果这没有帮助,请考虑使用 GroupJoin。

GoodSections = assessment.UserSections
    .Where(userSection => userSection.Section.SectionType != SectionTypeEnum.Reading
                       && userSection.Percentage < userSection.Section.ReadinessRangeHigh 
                       && userSection.Percentage > userSection.Section.ReadinessRangeLow)
    .Count(),

自己加入小组:

var test = dbContext.UserAssessments.GroupJoin(
    dbContext.UserSections,

    userAssessment => userAssesment.Id      // from every Assessment take the primary key
    userSection => userSection.AssesmentId, // from every UserSection take the foreign key

    // parameter resultSelector: from every UserAssesment, with all its UserSections
    // make one new
    (userAssessment, userSectionsOfThisAssessment) => new
    {
        UserAssessmentID = userAssessment.ID,
        StartedDateTime = userAssessment.StartDateTime,
        CompletedDateTime = userAssessment.CompletedDateTime,

        // To get the name, we need to get the Assesment that my foreign key refers to
        AssessmentName = dbContext.Assessments
             .Where(assessment => assessment.AssessmentId == userAssesment.Id)
             .Select(assessment => assessment.Name)
             .FirstOrDefault(),

        GoodSections = ... // TODO
    });

我不确定,但在我看来,Section 和 UserSection 之间存在一对多的关系:每个 Section 都有零个或多个 UserSection;每个 UserSection 只属于一个 Section,即外键所指的 Section。

因此,对于每个 userSectionOfThisAssessment,我们需要获取外键引用的 Section:标准内部连接

GoodSections = userSectionsOfThisAssessment.Join(
    dbContext.Sections

    userSection => userSection.SectionId,    // take the foreign key to the section
    section => section.Id,                   // take the sections's primary key

    (userSection, section) => new
    {
        SectionType = section.SectionType,

        Percentage = userSection.Percentage,
        MaxPercentage = section.ReadinessRangeHigh,
        MinPercentage = section.ReadinessRangeLow,
    })
    .Where(joinResult => joinResult.SectionType != SectionTypeEnum.Reading
                      && joinResult.Percentage < MaxPercentage
                      && joinResult.Percentage > MinPercentage)
    .Count(),
    

对于 GoodSection,我们需要将 userSectionsOfThisAssessment 与所有部分进行 GroupJoin。我不确定这是一个一对多的关系,还是一个男人

        MyAssessments = await test.Select(assessment => new MyAssessmentVM()
        {
            Assessment = assessment.Assessment.Name,
            CompletedDateTime = assessment.CompletedDateTime,
            StartedDateTime = assessment.StartDateTime,
            UserAssessmentID = assessment.ID,
            GoodSections = assessment.UserSections.Where(userSection => userSection.Section.SectionType != SectionTypeEnum.Reading)
                        .Count(n => n.Percentage < n.Section.ReadinessRangeHigh && n.Percentage > n.Section.ReadinessRangeLow)
        }).ToListAsync();

【讨论】:

  • 您对此的所有假设都是正确的。这些是一对多的关系。部分是构建的管理对象,用户部分是完成该部分的人的记录。所以它可能是空的。我正在查看您的代码,很抱歉我还没有标记答案,我正在尝试消化这个。
  • 另外,我分离了 where 语句,因为我最初在 where 语句中拥有它并且它一直抛出错误。它分开的唯一原因是我试图测试并弄清楚如何让它工作。
猜你喜欢
  • 2016-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-04
  • 1970-01-01
  • 1970-01-01
  • 2017-01-20
相关资源
最近更新 更多