F#linq2SQL错误或我的失败?

时间:2011-02-21 09:08:01

标签: linq-to-sql f#

我已经将错误发送到fsbugs@microsoft.com 我还将此链接添加到信中以获取更多说明,代码突出显示,讨论和也许有人找到某种方法来避免它< / strong>,因为我非常喜欢并希望使用。

代码:

<@ seq {for a in db.ArchiveAnalogs do
            for d in db.Deltas do
                if a.ID = d.ID then
                    if a.Value > d.DeltaLimit then
                        yield a.Date, d.AboveMessage
                    else if a.Value < d.DeltaLimit then
                        yield a.Date, d.BelowMessage}
     @> |> query |> Array.ofSeq

与更新相同的错误消息:

   <@ seq {for a in db.ArchiveAnalogs do
                        for d in db.Deltas do
                            if a.ID = d.ID && a.Value > d.DeltaLimit then
                                yield a.Date, d.AboveMessage
                            elif a.ID = d.ID && a.Value < d.DeltaLimit then
                                yield a.Date, d.BelowMessage}
                 @> |> query |> Array.ofSeq

错误讯息:

The following construct was used in query but is not recognised by the
     

F#-to-LINQ查询翻译:调用   (没有,         System.Collections.Generic.IEnumerable 1[System.Tuple 2 [的System.DateTime,System.String]]   单[元组2](System.Tuple 2 [的System.DateTime,System.String]),         [NewTuple(PropertyGet(Some(a),System.DateTime Date,[]),                    PropertyGet(Some(d),System.String AboveMessage,   []))])这不是有效的查询   表达。检查规格   允许查询并考虑移动   一些查询出来的报价

固定

代码:

    let px =
        query <| 
        <@ seq { for cl in db.Dictionaries -> cl }
                    |> Seq.filter(fun x -> x.ID_Line = l1 || x.ID_Line = l2) @>
        |> fun pquery ->
            query <|
            <@ seq { for cd in db.DeltaCompares do
                        for cl1 in pquery do
                                            if cd.IID1 = cl1.IID then
                                                for cl2 in pquery do
                                                    if cd.IID2 = cl2.IID then
                                                        yield cl1
                                                        yield cl2 } @>
            |> List.ofSeq

更新时出现同样的错误:

            let p =
                [for cl in db.Dictionaries -> cl]
                |> Seq.filter(fun x -> x.ID_Line = l1 || x.ID_Line = l2)
                |> fun pquery ->
                    <@ seq { for cd in db.DeltaCompares do
                                for cl1 in pquery do
                                    for cl2 in pquery do
                                    if cd.IID1 = cl1.IID && cd.IID2 = cl2.IID then
                                        yield cl1, cl2 } @>
                    |> query |> Seq.collect(fun a -> [fst a; snd a])

错误讯息:

  

以下构造用于查询但不是   由F#-to-LINQ查询识别   翻译:致电(无,         System.Collections.Generic.IEnumerable`1 [LinqBase.Dictionary]   SingletonDictionary,         [cl1])这不是有效的查询表达式。检查规格   允许查询并考虑移动   一些查询出来的报价

固定

我不确定我是否做得正确所以我还要求您确认这是一个错误还是没有错误

1 个答案:

答案 0 :(得分:2)

第一种情况中,我认为F#-to-LINQ转换器可能在嵌套if上失败。你试过了吗(...)

编辑 [第二次尝试] :它也可能失败,因为我们使用if而没有else子句。如果您总是使用option类型返回某些内容然后过滤掉None值(可能有一种方法可以让它更好,但让我们从这开始),该怎么办:

<@ seq {for a in db.ArchiveAnalogs do
            for d in db.Deltas do
              yield
                if a.ID = d.ID && a.Value > d.DeltaLimit then
                  Some(a.Date, d.AboveMessage)
                elif a.ID = d.ID a.Value < d.DeltaLimit then 
                  Some(a.Date, d.BelowMessage)
                else None }
     @> |> query |> Seq.choose id |> Array.ofSeq

第二种情况中,可能会失败,因为for嵌套在if中。我试试这个(...)

编辑:这实际上是错误地使用LINQ(它也不适用于C#)。问题是你正在收集内存中的一些数据(pquery),然后将其作为输入传递给LINQ(这样它就必须将数据发送回SQL服务器。

您可以尝试这样编写(顺便说一句:我认为使用|> fun x ->是一个奇怪的构造,只需使用let就能编写相同的内容):

let pquery = <@ db.Dictionaries
            |> Seq.filter(fun x -> x.ID_Line = l1 || x.ID_Line = l2) @>
let px = 
  <@ seq { for cd in db.DeltaCompares do
             for p in %pquery do ... } |> query

这是使用引用拼接。有关此功能的更多信息,请see my article(搜索拼接)。