3

最近導入された F# 3.0 クエリ理解構文を使用して、部品表のようなクエリを定義しようとしています。メモリ内コレクションの seq 内包表記を使用してこの種のクエリを定義することは可能ですが、yield!リモート可能な IQueryable ソースを対象とするクエリ内包表記にそれらを変換することは欠かせませんでした。難しい部分は、再帰パターンから共通テーブル式を認識するようにプロバイダーを「トレーニング」することだと思います。

何か案は?

4

1 に答える 1

5

残念ながら、F# 3.0 でサポートされている現在のクエリ構文では、再帰クエリを処理できるとは思いません。主な問題は、F# 3.0 が、主に C# 用に設計された標準実装に依存しているIQueryableため、再帰構造を想定していないことです。

これをサポートするのはかなり難しいと思います。独自の F# クォーテーションを SQL トランスレータに実装する (これは難しい) か、再帰を含む F# クォーテーション (クエリ) を受け取り、再帰を LINQ to SQL トランスレータが実行できるものに変換するある種のプリプロセッサを実装することができます。対処します(しかし、これもおそらく難しいでしょう)。

一般に、アプローチは独自のクエリ ビルダーを定義することです。

open System.IO
open Microsoft.FSharp.Quotations

type MyQueryBuilder() =
  member x.For(a, body) = Seq.collect body a
  member x.Quote(e) = e
  member x.YieldFrom(s) = s
  member x.Run(e:Expr<'T>) : 'T = failwithf "%A" e

// Example using the custom query builder
// (fails, printing the quoted query)
let mquery = MyQueryBuilder()    
let n = [1 .. 10]

let rec nums a : seq<int> =
  mquery { for b in n do
           yield! nums b }

このRunメソッドでは、クエリを表す引用を取得します。それを前処理し、すべての呼び出しMyQueryBuilderを標準query操作の呼び出しに置き換え、再帰を別のものに置き換えることができます。query.Run次に、(標準IQueryable実装を実行するために)呼び出すことができます。

私が言ったように、これを実装するのはおそらく非常に難しいでしょう - しかし、おそらく、簡単に対処できる特定の種類の再帰があれば、それはオプションかもしれません. ただし、LINQ to SQL が標準パターンの共通テーブル式を生成しない場合、それらを生成するようにトレーニングすることはできないと思います。私の知る限り、トランスレーターは実際には拡張可能ではありません。

于 2012-04-30T16:26:52.073 に答える