2017-03-15 31 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查詢。