Tas*_*que 3 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());
Run Code Online (Sandbox Code Playgroud)
在实体框架它给我结果像这样
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
Run Code Online (Sandbox Code Playgroud)
在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
Run Code Online (Sandbox Code Playgroud)
问候
作为寻找答案的方法......
要按照@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());
Run Code Online (Sandbox Code Playgroud)
更改(可能并非全部有效):
1.删除了品牌,因为它未在第二个查询中使用(您可以在第一个查询中将其用作连接,但如果其部分限制则不添加到新类型)
2简化了第一个查询生成的匿名类型中包含的内容 - 如果您只消耗了部分emp/sales/price,那么它可以更清楚地说明发生了什么
.3.在第一部分中添加对SalesMonth的限制(什么你正在做第二个)因为这可能会减少你的数据,提高性能,让你专注于实际出错的地方(我已经保留了第二个SalesMonth限制)
4.我认为SKUID是sk的相关部分分组而不是所有对象都是必需的