2017-03-03 17 views
3

は、私は、私は再帰的に「クエリの規準」のリストを畳むことにより、何かをやろうとしているSqlProvider再帰的に構成するクエリ

式ツリーのみにコンパイルされますように
type Criterion = { 
    Column : string 
    Operator : string 
    Value : string 
} 

一度SQLを実行すると、データベースに何回もヒットしません。私はいくつかのアプローチ、最も成功したのは、関数translateOpnValuが

let translateOpnValu (c:Criterion) = 
    match c.Operator with 
    |"%=%" -> (=%), sprintf "%%%s%%" c.Value 
    |_  -> (=), c.Value 

私は場合、私はこのexcpetion

System.Exception: Unsupported expression. Ensure all server-side objects appear on the left hand side of predicates. The In and Not In operators only support the inline array syntax. InvokeFast(elem.GetColumn("Source Code"), value(FSI_0006+acc'@38-2), "%BEN%") 
at Microsoft.FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation(FSharpExpr e) 
at Microsoft.FSharp.Linq.QueryModule.EvalNonNestedInner(CanEliminate canElim, FSharpExpr queryProducingSequence) 
at Microsoft.FSharp.Linq.QueryModule.EvalNonNestedOuter(CanEliminate canElim, FSharpExpr tm) 
at [email protected]nq-ForwardDeclarations-IQueryMethods-Execute[a,b](FSharpExpr`1) 
at FSI_0006.evaluate(FSharpOption`1 acc, FSharpList`1 qrys) in F:\code_root\vs2015\F\CAMS\CAMS\scratch.fsx:line 47 
at <StartupCode$FSI_0007>[email protected]() in F:\code_root\vs2015\F\CAMS\CAMS\scratch.fsx:line 60 

を取得しています。この

let rec eval (acc : IQueryable<SourceEntity> option) (qrys : Criterion list) = 
match qrys with 
|[] -> acc 
|x :: xs -> let acc' = let op,valu = translateOpnValu x 
         match acc with 
         |Some acc' -> query { 
              for elem in acc' do 
              where (elem.GetColumn x.Column op valu) 
              select elem 
            } |> Some 
         |None  -> query { 
              for elem in ctx.Dbo.Source do 
              where (elem.GetColumn x.Column op valu) 
              select elem 
            } |> Some 
      eval acc' xs 

のようなものですが試してみましたtranslateOpnValuから返された 'op'を暗黙の演算子(=/=%)に置き換えても問題ありません。暗黙の演算子は、より一般的なもののに対し、(>ブール - - >文字列)

私はそれがオペレータの種類が制約になっている返されたことと関係している感じています。より一般的な演算子を返すtranslateOpnValu関数を取得するにはどうすればよいですか?または、おそらくそれはまったく問題ではありません...

+1

あなたの 'op'は演算子として指定されていないので、中置記法では適用できません。 –

+0

おかげで、素晴らしい提案を、valu' 'OP(elem.GetColumn x.Column)悲しいかな、私はまだ同じ例外.... –

+1

は、その後、私はSqlProviderの引用パーサは演算子のみ自分自身を期待していることを前提となりを得る:代わりに接頭辞を試してみてくださいどんな形でもエイリアス化されていません。 'translateOpnValu'からの引用を返してスプライシングしてみてください。 –

答えて

3

@Fyodorが正しい - SQLプロバイダが関数を適切に受け取るためには、引用符で囲み、それをクエリ式にスプライスする必要があります。このようなものはうまくいくはずです:

let translateOpnValu (c:Criterion) = 
    match c.Operator with 
    |"%=%" -> <@ (=%) @>, sprintf "%%%s%%" c.Value 
    |_  -> <@ (=) @>, c.Value 

// ... 

query { 
    for elem in acc' do 
    where ((%op) (elem.GetColumn x.Column) valu) 
    select elem 
} 
関連する問題