【问题标题】:Get Total Count and Filter Results in one LINQ query?在一个 LINQ 查询中获取总计数和过滤结果?
【发布时间】:2021-11-16 07:20:58
【问题描述】:

我有一个查询,它基于连接(与此问题无关)获取对象列表,并筛选创建日期是否在过去 60 天内。这是有效的。我想做的是:

  1. 在没有 createdDate where 子句的情况下知道查询中有多少对象,并返回 ResultObj WITH the createdDate where 子句的列表。返回对象在我看来更像这样:
public class QueryResult 
{
    public long TotalPossibleCount {get; set;}
    public List<ResultObj> Results {get; set;}
}
IQueryable<ResultObj> res = 
    from tA in ctx.TableA
    join tB in ctx.TableB on tA.Id equals tb.CustId
    where tA.Id == 12345 && 
        tB.CreatedDate >= DateTime.Now.AddDays(-60)
    select new ResultObj
    {
        // some object properties
    };

return await res.OrderByDescending(x => x.CreatedDate).ToListAsync();

这可以在一个查询中完成吗?如果我没有 tb.CreatedDate &gt;= ... 加上它的数据对象列表,请计算所有可能的数量?

【问题讨论】:

  • 完成这项工作需要大量人为的 SQL 代码。请记住,SQL 始终只返回一个平面结果集,这意味着 每一 行必须包含一个具有计数值的列,每行的值相同。这是对空间(带宽)的浪费,而且通常不值得在资源管理方面付出努力。 Tl;dr 使用两个查询。
  • 我就是这么想的,但希望以另一种方式更有效。

标签: linq entity-framework-core linq-to-sql


【解决方案1】:

您可以通过以下查询和一次往返数据库来做到这一点:

var taFiltered = ctx.TableA.Where(x => x.Id == 12345);

var joined = 
    from tA in taFiltered
    join tB in ctx.TableB on tA.Id equals tb.CustId
    select new { tA, Tb };
    
var res = 
    from tA in taFiltered
    select new QueryResult
    {
        TotalPossibleCount = joined.Count(),
        Results = ctx.TableB
            .Where(tB => tA.Id == tB.CustId 
                tB.CreatedDate >= DateTime.Now.AddDays(-60)
            .OrderByDescending(x => x.CreatedDate)
            .Select(x => new ResultObj
            {
                 // some object properties
            }
            .ToList()
    };

return await res.FirstOrDefautAsync();

【讨论】:

  • 这是一个仅在名称上的单个查询。实际上,服务器执行 两个 查询并组合结果 - 一个用于计算计数,一个用于计算结果。总成本与执行两个查询相同
  • 这也是显而易见的。但我们也有改进,因为我们没有两次调用数据库。
猜你喜欢
  • 2021-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-23
  • 2011-01-26
  • 2017-02-21
  • 2021-04-26
  • 1970-01-01
相关资源
最近更新 更多