You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中如何合并两个IDbContext查询以获取关注俱乐部的比赛结果?

问题描述

我知道怎么从数据库取对应数据,但不确定C#里怎么实现这个需求:我有两个方法,第一个返回我关注的俱乐部列表,第二个返回指定俱乐部的比赛结果,现在想创建第三个方法,返回我关注的所有俱乐部的比赛结果。

获取关注俱乐部列表的代码

ImmutableArray<ClubInActiveSessionForMemberSqlModel> myClubs;
using (var context = _contextFactory.CreateDbContext())
{
    myClubs = await context
        .ClubMembers
        .SetTracking(false)
        .Where(ClubMember =>
            ClubMember.MemberId == memberId &&
            ClubMember.ClubMemberRegistrationStatusTypeId == ClubMemberRegistrationStatusTypes.Registered.Id &&
            (ClubMember.Club!.Session!.StartDateUtc > DateTime.UtcNow || ClubMember.Club!.Session.EndDateUtc > DateTime.UtcNow))
        .Select(ClubMember => new ClubInActiveSessionForMemberSqlModel(
            ClubMember.ClubId,
            ClubMember.Club!.Name,
            ClubMember.Club.Session!.Id,
            ClubMember.Club.Session.Name,
            ClubMember.Club.Session.SessionTypeId,
            ClubMember.Club.ClubStanding!.ClubMatchWins,
            ClubMember.Club.ClubStanding.ClubMatchLosses
        ))
        .ToImmutableArrayAsync();
}

获取指定俱乐部比赛结果的代码

using (var context = _contextFactory.CreateDbContext())
{
    return await context
        .Clubs
        .SetTracking(false)
        .Where(t => t.Id == ClubId)
        .Select(t => new AllMatchResultsForClubByIdSqlModel(
            ClubId,
            t.Name,
            t.SessionId,
            t.Position1ClubMatches!
                .Where(tm => !completedOnly || (tm.ClubMatchResult != null && tm.ClubMatchResult.WinnerClubId.HasValue))
                .AsQueryable()
                .Select(selectClubMatchResultSqlModelExpression)
                .AsEnumerable(),
            t.Position2ClubMatches!
                .Where(tm => !completedOnly || (tm.ClubMatchResult != null && tm.ClubMatchResult.WinnerClubId.HasValue))
                .AsQueryable()
                .Select(selectClubMatchResultSqlModelExpression)
                .AsEnumerable()))
        .FirstOrDefaultAsync();
}

请问能不能把这两个查询合并成一个?我查过类似SQL语法的问题,但不确定C#里怎么实现。


解决方案

完全可以合并成一个查询,核心思路是从ClubMembers出发,先筛选出用户关注的有效俱乐部,再直接关联查询这些俱乐部的比赛结果,避免多次数据库往返。

合并后的完整代码

using (var context = _contextFactory.CreateDbContext())
{
    return await context
        .ClubMembers
        .SetTracking(false)
        .Where(cm =>
            cm.MemberId == memberId &&
            cm.ClubMemberRegistrationStatusTypeId == ClubMemberRegistrationStatusTypes.Registered.Id &&
            (cm.Club!.Session!.StartDateUtc > DateTime.UtcNow || cm.Club.Session.EndDateUtc > DateTime.UtcNow))
        // 直接关联Club实体,一次性获取比赛数据
        .Select(cm => new AllMatchResultsForClubByIdSqlModel(
            cm.ClubId,
            cm.Club!.Name,
            cm.Club.SessionId,
            // 处理Position1的比赛结果
            cm.Club.Position1ClubMatches!
                .Where(tm => !completedOnly || (tm.ClubMatchResult != null && tm.ClubMatchResult.WinnerClubId.HasValue))
                .Select(selectClubMatchResultSqlModelExpression),
            // 处理Position2的比赛结果
            cm.Club.Position2ClubMatches!
                .Where(tm => !completedOnly || (tm.ClubMatchResult != null && tm.ClubMatchResult.WinnerClubId.HasValue))
                .Select(selectClubMatchResultSqlModelExpression)
        ))
        .ToImmutableArrayAsync();
}

关键说明

  1. 单次数据库请求:EF Core会自动将这个查询转换为带JOIN的SQL,只需要一次数据库往返,比先查俱乐部列表再逐个查比赛结果的性能更高。
  2. 简化子查询:移除了原代码中不必要的AsQueryable()和AsEnumerable(),导航属性本身支持LINQ查询,EF Core能直接将子筛选逻辑转换为SQL。
  3. 返回类型调整:返回ImmutableArray<AllMatchResultsForClubByIdSqlModel>,对应所有关注俱乐部的比赛结果集合。
  4. 空值处理:保留原代码的空值运算符!,确保EF Core能正确解析导航属性(如果实体配置中这些导航属性是必选的,可考虑调整实体定义去掉空值运算符)。

额外优化提示

确保selectClubMatchResultSqlModelExpression是纯表达式树(不包含无法转换为SQL的本地方法),这样整个查询逻辑都会在数据库端执行,性能达到最优。

内容的提问来源于stack exchange,提问作者NewCSharp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 14:10:25