2016-10-06 7 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의 주위에 방법이 있다고 생각한다. 내가 쿼리에 대한 템플릿으로 그 예를 사용하려고 할 때, :

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

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() 조각 오류 부족이 나는이 일어날 가입 할 수있는 방법과result의 일치하지 않는 행을 None (또는 다른 null SQL null 값)으로 채워 모든 쿼리를 내 레코드 유형으로 전달할 수 있도록 모든 행을 선택 하시겠습니까?

이상적으로, 일치하지 않는 행의 출력은 (아래 손으로 만든 절단 결과)

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.LeftOuterJoinsource 참조).).

당신은, 그럼 그냥 (하지만 주 - 새로 바인딩 row 값을 선택하려면, 하지result 순서)DefaultIfEmpty없이 추가 for 루프 를 추가 조인 전통적인 왼쪽의 결과를 원하는 경우 :

당신은을 적용 할 수 있도록이는하지만, null 필드 값이 누락 된 MDR_0916 항목, 특별하지 MDR_0916 값을 당신에게 null 값을 줄 것이다 는
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) 
    } 

주 후자가 필요한 경우 사후 처리 단계.

+0

'null'필드 값을 사용하여 MDR_0916 값을 생성하기위한 후 처리 단계를 적용 해 주신 것에 대해 큰 감사와 감사를드립니다. 필자는 필자가 필요로했던'MDR ... '필드를 선택하고 사용자 정의 유형으로 전달하는 방법을 다시 작성했습니다. – Steven