2015-11-17 93 views
1

我很努力地將sql語句轉換成Linq。Linq多重連接 - 結果太多

我得到的結果太多,無法計算出正確的語法應該是什麼。

這是SQL:

SELECT   
    Client_Details_Legacy.FullName, 
    Client_Details_Legacy.AddressLine1, 
    Client_Details_Legacy.AddressLine2, 
    Client_Details_Legacy.AddressLine3, 
    Policy_Property.PolicyNumber, 
    Policy_Property.CoverTo, 
    Clients.Id 
FROM    
    Clients 
    INNER JOIN Policy_Property 
     ON Clients.Id = Policy_Property.Client_Id 
    INNER JOIN Client_Details_Legacy 
     ON Clients.Client_Details_Legacy_Id = Client_Details_Legacy.Id 
WHERE   
    (Policy_Property.CoverTo >= CONVERT(DATETIME, '2015-12-01 00:00:00', 102)) 
    AND (Policy_Property.CoverTo <= CONVERT(DATETIME, '2015-12-31 00:00:00', 102)) 
ORDER BY 
    Clients.Id 

這是接近我設法讓我的LINQ的聲明,但它返回更多的行比它應該是。

我懷疑它的東西做加盟,但我似乎無法得到正確的語法:

var query = from clients in db.Clients 
         .Include("Client_Details_Legacy") 
         .Include("Policies_Property") 
      where clients.Client_Details_Legacy.Country.Code == countryCode 
        && clients.Policies_Property.Any(x => x.CoverTo >= CoverToStart 
                 && x.CoverTo <= CoverToEnd) 
      select clients; 

return query.ToList(); 

這是我的模型......

public class Client 
{ 
    public int Id { get; set; } 
    [Index] 
    [MaxLength(50)] 
    public string ClientNumber_Legacy { get; set; } 
    [Index] 
    [MaxLength(50)] 
    public string ClientNuber_Websure { get; set; } 
    public Client_Details_Enhanced Client_Details_Enhanced { get; set; } 
    public Client_Details_Legacy Client_Details_Legacy { get; set; } 
    public Client_Details_Websure Client_Details_Websure { get; set; } 
    public List<Policy_Motor> Policies_Motors { get; set; } 
    public List<Policy_Property> Policies_Property { get; set; } 
} 

public class Policy_Property 
{ 
    [Key] 
    [MaxLength(50)] 
    public string PolicyNumber { get; set; } 
    public Policy_Property_Details_Legacy Policy_Property_Details_Legacy { get; set; } 
    public Policy_Property_Details_Enhanced Policy_Property_Details_Enhanced { get; set; } 
    public DateTime CoverFrom { get; set; } 
    public DateTime CoverTo { get; set; } 
    public List<Insured_Property> Insured_Properties { get; set; } 
} 

public class Client_Details_Legacy 
{ 
    public int Id { get; set; } 

    public ws_lookup_ClientType ClientType { get; set; } 

    [DisplayName("Title")] 
    public ws_lookup_Title Title { get; set; } 

    [Index] 
    [DisplayName("Full Name")] 
    [MaxLength(250)] 
    public string FullName { get; set; } 

    public string NationalIdNumber { get; set; } 
    public string EmailAddress { get; set; } 
    [DisplayName("Address Line 1")] 
    [MaxLength(250)] 
    public string AddressLine1 { get; set; } 

    [DisplayName("Address Line 2")] 
    [MaxLength(250)] 
    public string AddressLine2 { get; set; } 

    [DisplayName("Address Line 3")] 
    [MaxLength(250)] 
    public string AddressLine3 { get; set; } 

    [DisplayName("Address Line 4")] 
    [MaxLength(250)] 
    public string AddressLine4 { get; set; } 

    [DisplayName("Country")] 
    public ws_lookup_Country Country { get; set; } 

    [DisplayName("Parish")] 
    public ws_lookup_Parish Parish { get; set; } 

    [DisplayName("Home Telephone Number")] 
    [MaxLength(250)] 
    public string HomeTelephoneNumber { get; set; } 

    [DisplayName("Work Telephone Number")] 
    [MaxLength(250)] 
    public string WorkTelephoneNumber { get; set; } 

    [DisplayFormat(DataFormatString = "{0:dd MMM yyyy}")] 
    [DisplayName("Date of Birth")] 
    public DateTime? DateOfBirth { get; set; } 

    [DisplayName("Gender")] 
    public ws_lookup_Gender Gender { get; set; } 

    [DisplayName("Loyalty Card")] 
    [MaxLength(50)] 
    public string LoyaltyCard { get; set; } 

    [DisplayName("Occupation")] 
    public ws_lookup_Occupation Occupation { get; set; } 
} 

誰能幫我找到了什麼我做錯了嗎?

+0

爲什麼會出現在LINQ嘗試的國家代碼,而不是在原來的SQL? –

回答

3

部分原因是,您的查詢,而你試圖返回特定的客戶端返回的某些數據。但這不會起作用,因爲客戶與多種政策相關聯,但您只對特定政策感興趣。以下應該給出與SQL相同的結果。

var query = from client in db.Clients 
      from policy in client.Policies_Property 
      where policy.CovertTo >= ConvertToStart && policy.ConverTo <= ConverToEnd 
        && client.Client_Details_Legacy != null 
      select new 
      { 
       client.Client_Details_Legacy.FullName, 
       client.Client_Details_Legacy.AddressLine1, 
       client.Client_Details_Legacy.AddressLine2, 
       client.Client_Details_Legacy.AddressLine3, 
       policy.PolicyNumber, 
       policy.CoverTo, 
       client.Id 
      }; 

注意我離開了client.Client_Details_Legacy.Country.Code == countryCode因爲這是未出現在SQL。

+0

如果客戶端沒有匹配的ClientDetailLegacy - 在原來它會被過濾,但不會被過濾,因爲我讀這個代碼.. –

+0

@DavidB好點。固定。 – juharr

0

我認爲這裏的線是問題:

clients.Policies_Property.Any(x => x.CoverTo >= CoverToStart && x.CoverTo <= CoverToEnd) 

採用Any將返回所有記錄,如果1成立,而不是隻返回滿足該條款的行。

Enumerable.Any:確定序列中的任何元素是否滿足條件。

,而不必查看數據或測試手段,你可以嘗試...問題的

where clients.Client_Details_Legacy.Country.Code == countryCode 
       && (clients.Policies_Property.CoverTo >= CoverToStart && 
        clients.Policies_Property.CoverTo <= CoverToEnd) 
+0

我同意這是問題所在,但是您還沒有提出解決方案,因此作爲評論會比答案更好。 – juharr

+0

@juharr,我只是打字:) – christiandev

+0

'Policies_Property'是一個'List ',所以它不會有'CovertTo'屬性。 – juharr

1

你的SQL語句,可以很容易地轉換爲LINQ是這樣的:

var query = from clients in db.Clients 
         join cdl in db.Client_Details_Legacy on cdl.Id = clients.Client_Details_Legacy_Id 
         join pp in db.Policies_Property on pp.Client_Id = clients.Id 
      where pp.CoverTo >= CoverToStart && pp.CoverTo <= CoverToEnd 
      select new { 
       FullName = cdl.FullName, 
       AddressLine1 = cdl.AddressLine1, 
       AddressLine2 = cdl.AddressLine2, 
       AddressLine3 = cdl.AddressLine3, 
       PolicyNumber = pp.PolicyNumber, 
       CoverTo = pp.CoverTo, 
       Id = clients.Id 
       }; 
return query.OrderBy(q => q.Id).ToList(); 
+0

我建議您閱讀[不要使用Linq的加入。導航!](https://coding.abel.nu/2012/06/dont-use-linqs-join-navigate/) – juharr

+0

那麼,使用導航屬性並不是什麼新東西,但也不一定是更好的方式來翻譯SQL查詢。想象一下,無論出於何種原因,這些實體都沒有導航屬性,那麼如何進行LINQ查詢呢? – Ramanagom

+0

然後你會使用連接,但重點是導航屬性是可取的,如果存在,因爲它們在這種情況下。 – juharr