优化或抛弃LINQ查询?

时间:2014-01-17 16:02:33

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

所以我有一个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

单击clients列的求和函数将显示以下网格数据:

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中进行优化和完成?谢谢你的建议!

2 个答案:

答案 0 :(得分:4)

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

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

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

答案 1 :(得分:0)

仅在内存中执行分组?解决你的问题?

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();