2012-03-03 30 views
3

次のクエリは、LINQ to SQLで正常に動作しています。今、私は私が私が私にこのLINQ to Entity FrameworkのSQLクエリの問題

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 

のような正しい結果を取得していますL2Sで、この

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 

ような結果与えている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()); 

Entity Frameworkのにそれを変更したいですよろしくお願いします。

+2

私は多くの書式を編集しました - タブはMarkdownとうまく対話しません。 –

+0

ありがとう!嘆願は問題を見ている。私の主な問題は月間販売がすべてのSkusで繰り返されていることです – Tassadaque

+0

'ToList()'部分に注目しました。これは 'lstSale'の違いを見ることができることを意味します。残りはLINQ to Objects 。 –

答えて

5

答えを見つけるためのアプローチとして...

@ Jon Skeetの示唆によれば、それを単純化し、LINQ to SQLとEntityFrameworkを比較するためにlstSaleで取得しているものを調べる必要があります。

次のようなものが役立つかもしれません(私はすべてのソースオブジェクトをチェックしているわけではないので、構文的に正しいとは限りませんが、クエリを見ているだけです)。

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番目のクエリで消費されていないため、新しいタイプに追加最初に参加しなくて(あなたがそれを使用することができます
)2.最初のクエリによって生成された匿名型に含まれるものを簡略化します。もしあなたがconsuminのみならgの部分をemp/sales/priceとすると、何が起きているかが明確になる可能性があります。
3.最初の部分のSalesMonthに制限を追加しました。あなたは実際に私はSKUIDは、オブジェクトのすべてをグループ化していないため、SKの関連する部分であると仮定し
4(Iが所定の位置に二SalesMonth制限を残した)間違って何が起こっているのかに集中できるように

+0

ToList()はクエリを実行するので、foreachを使う必要はありません。 –

+0

foreachのポイントは、暫定的なステップでリストにあるものを見ることができるようにすることです。クエリの実行を強制することではありません。 – kaj

+0

OKですが、リストを見ているだけで簡単にクイックウォッチを使うことができます。 –

0

スタートによって要求されLINQのツーSQLの場合var lstSale = _sale.ToList();

ために生成されたSQLを調査し、あなたが使用することができます。

context.Log = Console.Out; 
あなたはプロバイダがint型のSQLを掘ることなく、表示されませんあなたのLINQクエリを処理する方法を、いくつかの違いがある場合もあります

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

またはDbContextのAPI

Console.WriteLine(_sale.ToString()); 

を使用することができますEntityFrameworkのObjectContextのAPIの場合

コマンド。