2016-10-06 34 views
5

查詢我有一個相對簡單的F#查詢表達式聯接:leftOuterJoin和`.DefaultIfEmpty()`在F#

let mdrQuery = 
    query { 
     for header in db.CustomerDetails do 
     leftOuterJoin row in db.MDR_0916 
      on (header.PID = row.PID) into result 
     select (result, header) 
     } 

這將返回每個headerresult但對於一個header,至今尚未row匹配, result只是一個空序列,當查詢結果被傳遞給一個自定義類型時,我得到一個錯誤,說明與row中的字段關聯的構造函數未定義。這對於在row中沒有匹配的任何header是有意義的,則返回null序列。舉個例子:

mdrQuery |> Seq.head;; 
val it : 
    seq<dbSchema.ServiceTypes.MDR_0916> * dbSchema.ServiceTypes.CustomerDetails 
= (seq [null], CustomerDetails {ACCOUNTMANAGER = null; 
          ACCOUNTSTATUS = "XC"; 
          ADDRESSLINE1 = null; 
          ADDRESSLINE2 = null; 
          ADDRESSLINE3 = null; 
          ADDRESSLINE4 = "123 PIG ROAD"... 

我懷疑有周圍the leftOuterJoin documentation here這一點,因爲一種方式。但是,當我嘗試使用這個例子作爲查詢模板:

let mdrQuery = 
    query { 
     for header in db.CustomerDetails do 
     leftOuterJoin row in db.MDR_0916 
      on (header.PID = row.PID) into result 
     for row in result.DefaultIfEmpty() do 
     select (result, header) 
     } 

.DefaultIfEmpty()件錯誤出與

error FS0039: The field, constructor or member 'DefaultIfEmpty' is not defined 

有沒有辦法,我可以使這個連接發生選擇每行,填充result中的不匹配行與None(或其他一些空的SQL空值),以便可以將整個查詢傳遞給我的記錄類型?

在理想情況下,輸出爲不匹配的行會是這樣的(由下面的手產生截短的結果)

mdrQuery |> Seq.head;; 
val it : 
    seq<dbSchema.ServiceTypes.MDR_0916> * dbSchema.ServiceTypes.CustomerDetails 
= (MDR_0916 {AIMExp = null; 
     AP = null; 
     APComp = null; 
     APEng = null; 
     APFine = null; 
     APForl = null;...}, 
CustomerDetails {ACCOUNTMANAGER = null; 
          ACCOUNTSTATUS = "XC"; 
          ADDRESSLINE1 = null; 
          ADDRESSLINE2 = null; 
          ADDRESSLINE3 = null; 
          ADDRESSLINE4 = "123 PIG ROAD"... 

編輯:This question/answer類似於礦,但包括ToOption result簡單地輸出一個Some (seq [null])

+1

在您的交互式輸出中,'result'不是一個空序列,而是一個元素的序列,而那個元素是'null'。 –

+0

感謝您的澄清。 – Steven

+4

'DefaultIfEmpty'是一個擴展方法,所以你需要'打開System.Linq'。 – kvb

回答

0

該文檔是錯誤的;在C#中,沒有直接等價於leftOuterJoin運算符,因此DefaultIfEmpty與普通聯接一起使用,但在F#中,您不需要此操作(查詢生成器會爲您執行此轉換 - 如果您好奇,請參見中的QueryBuilder.LeftOuterJoin )。

如果你想有一個傳統左派的結果加入,則只需添加額外的for沒有DefaultIfEmpty(但要注意 - 要選擇新綁定row值,result順序):

let mdrQuery = 
    query { 
     for header in db.CustomerDetails do 
     leftOuterJoin row in db.MDR_0916 
      on (header.PID = row.PID) into result 
     for row in result do 
     select (row, header) 
    } 

注意,這會給你nullMDR_0916條目中缺少的,沒有特殊MDR_0916值與null字段值,雖然如此,你可能想應用後期處理步驟,如果你需要後者。

+0

很好的回答,並且感謝你申請後處理步驟來創建'null'字段值的'MDR_0916'值的建議。我最終只選擇了我需要的'MDR ...'中的那些字段,並重新編寫了將它傳遞給自定義類型的方式。 – Steven