LINQ to SQL Query Issue в Entity Framework - PullRequest
3 голосов
/ 03 марта 2012

У меня следующий запрос работает нормально в 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());

В Entity Framework Это дает мне результат Вот так

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 ]

5 голосов
/ 03 марта 2012

Как подход к поиску ответа ...

Для диагностики, как предлагает @Jon Skeet, вам нужно упростить ее и посмотреть, что вы получаете в рамках lstSale, чтобы сравнить LINQ с 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 для группировки, и не весь объект требуется

0 голосов
/ 03 марта 2012

Начните с исследования сгенерированного SQL для var lstSale = _sale.ToList();

В случае Linq-To-SQL вы можете использовать:

context.Log = Console.Out;

В случае API EntityFramework ObjectContext вы можете использовать

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

или DbContext API

Console.WriteLine(_sale.ToString());

Может быть некоторая разница в том, как провайдеры обрабатывают ваш запрос Linq, который не будет виден без копания команд int SQL.

...