2012-03-03 110 views
3

我有以下查询在LINQ to SQL中正常工作。现在我想将其更改为实体框架实体框架中的LINQ to SQL查询问题

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

我已经编辑了很多格式 - 制表符不能很好地与Markdown配合使用。 – 2012-03-03 08:01:15

+0

谢谢!请认真看看这个问题。我的主要问题是每月销售重复所有skus – Tassadaque 2012-03-03 08:06:09

+0

我刚刚注意到'ToList()'部分 - 这意味着你应该能够看到'lstSale'的差异,因为其余的将在LINQ to Objects 。 – 2012-03-03 08:07:37

回答

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.简化第一个查询生成的匿名类型中包含的内容 - 如果您只是consumin g部分emp/sales/price那么它可能会使得它更清晰地发生什么
3.在第一部分中增加了对SalesMonth的限制(您在第二部分中做什么),因为这可能会减少数据,提高性能并允许你把重点放在什么实际发生错误(我留在原地第二SalesMonth限制)
4.我以为SKUID是SK进行分组的相关部分,而不是全部对象的需要

+0

ToList()运行查询,所以没有必要使用foreach。 – 2012-03-03 09:20:21

+0

foreach的要点是,您可以在临时步骤中查看列表中的内容。不是强制执行查询。 – kaj 2012-03-03 09:21:57

+0

好的,但对于收看列表OP,只需使用快速查看即可。 – 2012-03-03 09:28:08

0

开始通过调查生成的SQL为var lstSale = _sale.ToList();

在LINQ到SQL的情况下,你可以使用:

context.Log = Console.Out; 

在的EntityFramework ObjectContext的API的情况下,你可以使用

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

或的DbContext API

Console.WriteLine(_sale.ToString()); 

可以有一些差异供应商如何处理您的LINQ查询,而无需挖INT SQL这将不可见命令。