2017-03-03 1 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'를 암시 적 연산자 (=/= %)로 바꿉니다.

반환 된 연산자 유형이 (string -> string -> bool) 제약을 받는다는 사실과 관련이 있다는 느낌이 들지만 내재적 연산자는보다 일반적인 것입니다. 보다 일반적인 연산자를 반환하려면 translateOpnValu 함수를 어떻게 얻을 수 있습니까? 아니면 전혀 문제가되지 않습니다 ...

+1

'op'는 연산자로 명명되지 않았기 때문에 중위 표기법으로 적용 할 수 없습니다. 대신 접두사를 시도하십시오 :'op (elem.GetColumn x.Column) valu' –

+0

고마워, 좋은 제안, 아아, 나는 여전히 같은 예외를 얻는다 .... –

+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 
} 
관련 문제