fO中的leftOuterJoin和`.DefaultIfEmpty()`查询

时间:2016-10-06 13:58:03

标签: 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)
        } 

这会返回headerresult,但对于header中不匹配的rowresult只是一个空序列,当查询结果传递给自定义类型,我得到一个错误,即没有定义与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"...

我怀疑由于the leftOuterJoin documentation here而有办法解决这个问题。但是,当我尝试将该示例用作 my 查询的模板时:

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 个答案:

答案 0 :(得分:0)

文档错了;在C#中,没有直接等效的leftOuterJoin运算符,因此DefaultIfEmpty与普通联接一起使用,但在F#中您不需要此(查询构建器为您执行此转换 - 请参阅{如果你很好奇,可以在source中{1}}。

如果您想要传统左连接的结果,那么只需添加额外的QueryBuilder.LeftOuterJoin循环而不用 for(但请注意 - 您要选择新绑定的{ {1}}值, 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) } 值,而不会为null字段值提供特殊MDR_0916值,因此您可能希望如果您需要后者,请应用后处理步骤。