Entity Framework LINQ 多列计数(不同)

Entity Framework LINQ Multiple Column Count(Distinct)

我不完全确定如何将以下 SQL 翻译成 LINQ Fluent API。任何帮助都会很棒

select count(distinct thread.Id) as ThreadCount, count(distinct segment.Id) as SegmentCount
from Segment 
inner join SegmentCommunicator as SegmentCommunicator
    on Segment.Id = SegmentCommunicator.SegmentId
inner join Thread
    on Thread.Id = Segment.ThreadId
where SegmentCommunicator.CommunicatorId in (94, 3540, 6226, 10767, 20945)

目前,我知道如何在 2 个查询中执行此操作,但对于我来说,我无法弄清楚如何将其浓缩为一个。任何帮助将不胜感激

        var aggregate1 = _threadProvider
                .AsQueryable()
                .SelectMany(t => t.Segments)
                .Where(s => s.SegmentCommunicators.Any(sc => communicatorIds.Contains(sc.CommunicatorId)))
                .Select(s => s.ThreadId)
                .Distinct()
                .Count();

        var aggregate2 = _threadProvider
            .AsQueryable()
            .SelectMany(t => t.Segments)
            .Where(s => s.SegmentCommunicators.Any(sc => communicatorIds.Contains(sc.CommunicatorId)))
            .Select(s => s.Id)
            .Distinct()
            .Count();

您可以使用一个“基本”查询,但两个不同的计数将是单独的查询,使用尽可能小的数据集对查询进行一次补水:

var query = _threadProvider
            .AsQueryable()
            .SelectMany(t => t.Segments)
            .Where(s => s.SegmentCommunicators.Any(sc => communicatorIds.Contains(sc.CommunicatorId)))
            .Select(s => new {s.ThreadId, s.Id})
            .Distinct()
            .ToList();

var aggregate1 = query.Select(s => s.ThreadId)
                      .Distinct()
                      .Count();

var aggregate2 = query.Select(s => s.Id)
                      .Distinct()
                      .Count();    

可能能够使用GroupBy在一个查询中完成:

var query = _threadProvider
            .AsQueryable()
            .SelectMany(t => t.Segments)
            .Where(s => s.SegmentCommunicators.Any(sc => communicatorIds.Contains(sc.CommunicatorId)))
            .GroupBy(s => 1)  
            .Select(g => new 
                {
                    ThreadCount  = g.Select(s => s.ThreadId.Distinct().Count()), 
                    SegmentCount = g.Select(s => s.Id.Distinct().Count()), 
                });

但我怀疑底层查询提供程序是否会支持它(最多它将把它变成两个子查询)。

请注意,这两个查询的执行速度都不可能与原始 SQL 一样快,因为 SQL 可以在将结果返回到 Linq 之前优化查询。