在F#中使用leftOuterJoin和`.DefaultIfEmpty()`查询

Ste*_*ven 5 f#

我有一个相对简单的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)
        } 
Run Code Online (Sandbox Code Playgroud)

这将返回每个headerresult但对于一个header已经不匹配row,result只是一个空序列,当查询结果传递给自定义类型,我得到的是与一个字段相关联的构造函数的错误row没有定义.这对于任何header没有匹配的内容都是有意义的row,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"...
Run Code Online (Sandbox Code Playgroud)

由于这里leftOuterJoin文档,我怀疑有一种解决方法.但是,当我尝试将该示例用作我的查询的模板时:

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)
        }
Run Code Online (Sandbox Code Playgroud)

.DefaultIfEmpty()件作品错误了

error FS0039: The field, constructor or member 'DefaultIfEmpty' is not defined
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以使这种连接发生选择每一行,resultNone(或其他一些空的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"...
Run Code Online (Sandbox Code Playgroud)

编辑: 这个问题/答案与我的相似,但包括ToOption result输出a Some (seq [null]).

kvb*_*kvb 1

文档有误;在 C# 中,没有与leftOuterJoin运算符直接等效的操作符,因此DefaultIfEmpty与普通联接一起使用,但在 F# 中,您不需要它(查询生成器为您执行此转换 - 如果您好奇,请参阅QueryBuilder.LeftOuterJoin代码)。

如果您想要传统左连接的结果,则只需添加额外的循环即可for(但请注意 - 您想要选择新绑定的值,而不是序列): DefaultIfEmptyrowresult

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)
    }
Run Code Online (Sandbox Code Playgroud)

请注意,这将为您提供缺少的条目的null值,而不是带有字段值的特殊值,因此,如果您需要后者,您可能需要应用后处理步骤。MDR_0916MDR_0916null