【问题标题】:Optimize or ditch LINQ query?优化或放弃 LINQ 查询?
【发布时间】:2014-01-17 16:02:33
【问题描述】:

所以我有一个 LINQ(to SQL)查询,可以将信息从数据库中提取到网格中。有一个功能可以根据当前过滤器参数聚合网格数据,该参数将汇总网格数据中重复出现的“X”的数量。

例如,假设网格显示顾客对杂货店的访问。原始数据可能显示如下:

Date     | Name       | No. Prod   | Total $
--------------------------------------------
01/02/13 | Customer A | 4 products | $23.00 
01/02/13 | Customer B | 2 products | $3.26
01/02/13 | Customer C | 7 products | $47.42
01/16/13 | Customer A | 3 products | $26.22

点击客户列的求和功能会显示如下网格数据:

Cnt| Name       | Tot. Prod  | Total $  
--------------------------------------
2  | Customer A | 7 products | $49.22 
1  | Customer B | 2 products | $3.26
1  | Customer C | 7 products | $47.42

我的问题是我在 LINQ 查询中执行求和逻辑。我以为这会很快……但恰恰相反。这是一个示例。

Expression<Func<OrdersView, bool>> filter;
filter = m => m.RecordCreated >= fromDate && m.RecordCreated <= toDate && m.DepartmentID == _depID;

var ClientAggOrders = dataContext.OrdersView
    .Where(filter)
    .GroupBy(m => m.Name)
    .Select(gr => new
        {
            Name = gr.Key,
            Count = gr.Where(s => s.ID != null).Count(),
            id = gr.Select(s => s.ID),
            S1 = gr.Sum(s => s.Tare < s.Gross ? s.Tare : s.Gross),
            S2 = gr.Sum(s => s.Tare < s.Gross ? s.Gross : s.Tare),
            NetWeight = gr.Sum(s => s.NetWeight),
            Price = gr.Sum(s => s.NetPrice)
        }
    ).ToList();

我的问题是,为什么这是这样不好的做法? LINQ 允许在 SELECT 子句中使用这些表达式,但是执行所需的时间非常荒谬,以至于我认为它在任何现实世界的场景中都没有好处。

我是否使用了错误的 LINQ,我应该将我的逻辑移到查询之外,还是可以在 LINQ 中正确优化和完成?感谢您的建议!

【问题讨论】:

  • 这是LINQ to SQL吗?
  • 是的,抱歉我没说清楚。
  • 您需要检查 Linq 正在生成并发送到 SQL 进行评估的 SQL。有了所有的分组和总和,我猜 SQL 是可怕的。
  • 这条线看起来很可疑:id = gr.Select(s =&gt; s.ID), - 如果您按名称分组,为什么要尝试在组中提取单个 ID?
  • @PinnyM 客户端网格需要一个唯一的 ID 作为参考。

标签: c# sql linq linq-to-sql


【解决方案1】:

您可以使用 LINQPad 查看生成的 SQL。

由于 LINQ to SQL 的工作方式,id = gr.Select(s =&gt; s.ID) 导致为每个组执行一个子查询。删除它,然后在 GroupBy 中获取 ID+名称:.GroupBy(m =&gt; new{m.ID, m.Name})

您应该会发现生成的 SQL 现在将是一条语句,而不是主语句加上每个组的语句。

【讨论】:

  • 哇,非常感谢。我有一种感觉,这是一个相对简单的问题……你每天都会学到新的东西!性能提升就像白天和黑夜......你是救生员爱德华! ...现在我想起来了,我不敢相信我没有找到 Select() 子查询的嫌疑人。 LINQ 让我做一些非常愚蠢的事情 >.
【解决方案2】:

只在内存中进行分组?解决您的问题?

var ordersView = 
    dataContext.OrdersView
    .Where(m => m.RecordCreated >= fromDate && m.RecordCreated <= toDate && m.DepartmentID == _depID)
    .ToList(); 

var ClientAggOrders = ordersView.GroupBy(m => m.Name).Select(gr => new
{
    Name = gr.Key,
    Count = gr.Where(s => s.ID != null).Count(),
    id = gr.Select(s => s.ID),
    S1 = gr.Sum(s => s.Tare < s.Gross ? s.Tare : s.Gross),
    S2 = gr.Sum(s => s.Tare < s.Gross ? s.Gross : s.Tare),
    NetWeight = gr.Sum(s => s.NetWeight),
    Price = gr.Sum(s => s.NetPrice)
}).ToList();

【讨论】:

    猜你喜欢
    • 2019-04-15
    • 1970-01-01
    • 1970-01-01
    • 2021-06-14
    • 1970-01-01
    相关资源
    最近更新 更多