2017-03-15 129 views
1

这是SQL查询我想转换成LINQ查询:没有得到LEFT JOIN在LINQ查询拿起空行

SELECT 
    ContactID, 
    COUNT (ls.SoldToContactID) AS Count 
FROM 
    Contacts c 
    LEFT OUTER JOIN LeadSales ls on c.ContactID = ls.SoldToContactID 
GROUP BY 
    c.ContactID 

我碰到leadSales预期的结果,但我不从contacts中挑选出在leadSales中没有匹配的行。

var leadSales = (IQueryable of the LeadSales table) 
var contacts = (IQueryable of the Contacts table) 

BuyerList = from ls in leadSales 
    join contact in contacts on ls.SoldToContactID equals contact.ContactID into sb 
    from subBuyer in sb.DefaultIfEmpty() 
     group ls by new { 
      subBuyer.ContactID, 
      FirstName = subBuyer.FirstName, 
      LastName = subBuyer.LastName 
     } into g 
     select new LeadBuyersByStateItem 
     { 
      ContactID = g.Key.ContactID, 
      Name = g.Key.LastName + ", " + g.Key.FirstName, 
      LeadsCount = g.Count() 
     }; 

编辑:基于从伊万反馈

,我现在有这样的:

BuyerList = from contact in contacts 
         join ls in leadSales on contact.ContactID equals ls.SoldToContactID into c_ls 
         from ls in c_ls.DefaultIfEmpty() 
         group contact by new 
         { 
          ls.Contact.ContactID, 
          FirstName = ls.Contact.FirstName, 
          LastName = ls.Contact.LastName 
         } into g 
         select new LeadBuyersByStateItem 
         { 
          ContactID = g.Key.ContactID, 
          Name = g.Key.LastName + ", " + g.Key.FirstName, 
          LeadsCount = g.Count() 
         }; 

但是,这是引发此错误:

The cast to value type 'System.Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.

+3

你不会放弃:)我可以第三次关闭它,因为它仍然是http://stackoverflow.com/questions/3404975/left-outer-join-in-linq的重复。相反,这次我给你一个提示:'从c中的联系人加入ls到leadSales上的c.ContactID等于ls.SoldToContactID到ls中的c_ls中c_ls.DefaultIfEmpty()...'。希望你可以从那里管理它。 –

+0

[LINQ中的LEFT OUTER JOIN](http:// stackoverflow。com/questions/3404975/left-outer-join-in-linq) – mrfreester

+0

@Ivan,我已经在你最后的评论(第二次)之后尝试过了。算了。我只是要使用SQL并忘记了LINQ。 –

回答

3

问题最初的LINQ查询是你已经交换了左边和右边的p艺术,所以它相当于SQL LeadSales LEFT OUTER JOIN Contacts

与更新查询的问题是,group by子句使用ls.Contact,由于ls是左外侧的右端加入,也可以是null。要匹配SQL查询,请使用contact变量(保证存在的连接的左端)。另请注意,SQL COUNT(ls.SoldToContactID)不包括NULL值,因此您必须在LINQ查询中记录该值(没有直接的LINQ等效构造)。

所以SQL查询的直接LINQ翻译是这样的:

from c in contacts 
join ls in leadSales on c.ContactID equals ls.SoldToContactID into c_ls 
from ls in c_ls.DefaultIfEmpty() 
group ls by new 
{ 
    c.ContactID, 
    c.FirstName, 
    c.LastName 
} into g 
select new LeadBuyersByStateItem 
{ 
    ContactID = g.Key.ContactID, 
    Name = g.Key.LastName + ", " + g.Key.FirstName, 
    LeadsCount = g.Count(ls => ls != null) 
}; 

但是,如果你忘记了SQL查询,并专注于预期的结果,你会发现有更简单的LINQ/EF版本相同的查询。

最简单的是,如果你有一个从ContactLeadSale(我注意到你有一个从LeadSaleContact)像

public ICollection<LeadSale> LeadSales { get; set; } 

导航属性然后查询很简单:

from c in contacts 
select new LeadBuyersByStateItem 
{ 
    ContactID = c.ContactID, 
    Name = c.LastName + ", " + c.FirstName, 
    LeadsCount = c.LeadSales.Count() 
}; 

如果你没有这样的财产,你可以使用Count有条件:

from c in contacts 
select new LeadBuyersByStateItem 
{ 
    ContactID = c.ContactID, 
    Name = c.LastName + ", " + c.FirstName, 
    LeadsCount = leadSales.Count(ls => ls.SoldToContactID == c.ContactID) 
}; 

group join

from c in contacts 
join ls in leadSales on c.ContactID equals ls.SoldToContactID into c_ls 
select new LeadBuyersByStateItem 
{ 
    ContactID = c.ContactID, 
    Name = c.LastName + ", " + c.FirstName, 
    LeadsCount = c_ls.Count() 
}; 

总括来说,在任何情况下,你应该开始使用所需的表的LINQ查询。