实体框架中的LINQ to SQL查询问题

时间:2012-03-03 07:46:31

标签: c# linq entity-framework linq-to-sql entity-framework-4

我有以下查询在LINQ to SQL中正常工作。现在我想将其更改为Entity Framework

var _sale = from emp in setupEmployees
            join sales in vwSaleTargets on emp.EmployeeID equals sales.EmployeeID
            join price in vwPeriodPricings
               on new { sales.SKUID, sales.PeriodID } 
               equals new { SKUID = (int?)price.SKUID, PeriodID = (int?)price.PeriodID }
            join sk in setupSKUs on sales.SKUID equals sk.SKUID
            join br in setupBrands on sk.BrandID equals br.BrandID
            where emp.EmployeeID == 123 && sales.StartDate.Year == 2012 
            select new { emp, sales, price, sk, br };

var lstSale = _sale.ToList(); //to avoid n+1 queries in case of grouping
var sale2 = from x in lstSale
            group x by new { x.sk, x.emp } into grouping
            select new 
            {
                 EmployeeName = grouping.Key.emp.EmployeeName,
                 SKUID = grouping.Key.sk.SKUID,
                 SKUName = grouping.Key.sk.Title,
                 MonthSale =(double?)grouping
                          .Where(x => x.sales.StartDate.Month == 2 && 
                                      x.sales.StartDate.Year == 2012)
                          .Select(t=>t.sales.SalesQuantity)
                          .Sum(t=>t.Value)?? 0,
                 MonthSaleValue = (double?)grouping
                          .Where(x => x.sales.StartDate.Month == 2 && 
                                      x.sales.StartDate.Year == 2012)
                          .Sum(x => x.sales.SalesQuantity * x.price.ExFactoryPrice)  
                             ?? 0,
            };
Console.WriteLine(sale2.OrderBy(x => x.SKUName).ToList());

在实体框架中它给我结果像这样

Name SKUID SKUName MonthSale MonthSaleValue 
EMP1  36    SKU1     113     61375.95 
EMP1  17    SKU2     113     6656.83 
EMP1  18    SKU3     113     9984.68 
EMP1  19    SKU4     113     15169.12 

在L2S中我得到了正确的结果

Name SKUID SKUName MonthSale MonthSaleValue 
    EMP1  36    SKU1     74     40193.1 
    EMP1  17    SKU2     113     6656.83 
    EMP1  18    SKU3     461     40733.96
    EMP1  19    SKU4     2     268.48

此致

2 个答案:

答案 0 :(得分:5)

作为寻找答案的方法......

要诊断,正如@Jon Skeet所建议的那样,你需要简化它并查看你在lstSale中获得的内容,以便将LINQ to SQL与EntityFramework进行比较。

以下几行中的内容可能有所帮助(不一定在语法上正确,因为我没有检查所有的源对象,但是我只是查看查询并将其简化为可能的位置)

var _sale = from emp in setupEmployees
            join sales in vwSaleTargets on emp.EmployeeID equals sales.EmployeeID
            join price in vwPeriodPricings
               on new { sales.SKUID, sales.PeriodID } 
               equals new { SKUID = (int?)price.SKUID, PeriodID = (int?)price.PeriodID }
            join sk in setupSKUs on sales.SKUID equals sk.SKUID
            where emp.EmployeeID == 123 && sales.StartDate.Year == 2012 && sales.StartDate.Month == 2
            select new 
            { 
                EmployeeName = emp.EmployeeName, 
                StartDate = sales.StartDate,
                SalesQuantity = sales.SalesQuantity, 
                ExFactoryPrice = price.ExFactoryPrice, 
                SKUID = sk.SKUID,
                SKUName = sk.SKUName 
            };

var lstSale = _sale.ToList(); //to avoid n+1 queries in case of grouping

// Run through lstSale here
foreach(var item in lstSale)
{
  Console.WriteLine(item);
}

var sale2 = from x in lstSale
            group x by new { x.SKUID, x.EmployeeName } into grouping
            select new 
            {
                 EmployeeName = grouping.Key.EmployeeName,
                 SKUID = grouping.Key.SKUID,
                 SKUName = grouping.SKUName,
                 MonthSale =(double?)grouping
                          .Where(x => x.StartDate.Month == 2 && 
                                      x.StartDate.Year == 2012)
                          .Select(t=>t.SalesQuantity)
                          .Sum(t=>t.Value)?? 0,
                 MonthSaleValue = (double?)grouping
                          .Where(x => x.StartDate.Month == 2 && 
                                      x.StartDate.Year == 2012)
                          .Sum(x => x.SalesQuantity * x.ExFactoryPrice)  
                             ?? 0,
            };
Console.WriteLine(sale2.OrderBy(x => x.SKUName).ToList());

变更(可能并非全部有效):
1.删​​除品牌,因为它没有在第二个查询中使用(您可以在第一个查询中将其用作连接,但如果它的部分限制则不添加到新类型)
2.简化第一个查询生成的匿名类型中包含的内容 - 如果您只消耗了emp / sales / price的部分内容,那么它可以更清楚地说明发生了什么 3.在第一部分中添加了对SalesMonth的限制(你在第二部分中做了什么)因为这可能会减少你的数据,提高性能并让你专注于实际出错的地方(我已经保留了第二个SalesMonth限制)
4.我假设SKUID是sk用于分组的相关部分,并非所有对象都是必需的

答案 1 :(得分:0)

首先调查var lstSale = _sale.ToList();

生成的SQL

如果是Linq-To-SQL,您可以使用:

context.Log = Console.Out;

如果是EntityFramework ObjectContext API,您可以使用

Console.WriteLine(((ObjectQuery)_sale).ToTraceString());

或DbContext API

Console.WriteLine(_sale.ToString());

如果没有挖掘SQL命令,那么提供程序处理Linq查询的方式会有所不同。