左连接转换为内部连接在Linq

时间:2013-09-15 13:34:27

标签: asp.net sql-server linq sql-server-2008 entity-framework

我有两张桌子:

ProductCodes

Code             Year             PageNo
-----------------------------------------

Costs

Code             Year         City         QsNo            price
----------------------------------------------------------------

我希望保留特定year-pageNo中的所有代码,然后显示特定year-city-Qsno的成本(如果存在),对于不存在的成本,我返回null。

我写了这个查询:

var Result = from code in ent.ProductCodes
                         join cost in ent.Costs
                           on new { a = code.Year, b = code.Code } equals new { a = cost.Year, b = cost.Code }
                           into AllCosts
                         from OutPut in AllCosts.DefaultIfEmpty()
                         where code.PageNo == PageNo && OutPut.Year == Year && OutPut.City == City && OutPut.QsNo == Qsno
                         select new
                         {
                             ProductCode = code.Code
                             Col6 = OutPut.Price
                         };

但它会转换为INNER JOIN。问题出在哪里?

1 个答案:

答案 0 :(得分:1)

问题是你在加入后检查OutPut变量上的Year,City和QsNo ...但是如果OutPut为null(如果AllCosts中没有行,则会发生这种情况)这些检查将始终为false,因此对(代码,OutPut)将被where子句过滤掉。 EF检测到这一事实,并通过仅使用内部联接生成更有效的查询。

您真正想要做的是从成本中过滤掉候选行,而不是过滤(代码,成本)对。为此,您可以移动过滤器,因此它直接应用于“成本”表:

var Result = from code in ent.ProductCodes
                     join cost 
                       in ent.Costs.Where(c => c.Year == Year && c.City == City && c.QsNo == Qsno)
                       on new { code.Year, code.Code } equals new { cost.Year, cost.Code }
                       into AllCosts
                     from OutPut in AllCosts.DefaultIfEmpty()
                     where code.PageNo == PageNo
                     select new
                     {
                         ProductCode = code.Code
                         Col6 = OutPut.Price
                     };