Reputation: 1480
I want to use a generic query function like:
let filter predicateFn =
predicateFn |>
fun f s -> query { for x in s do
where (f(x))
select x }
Where f should be a predicate function. Obviously, this cannot be translated to a sql query. But is there a solution for this problem. I have seen sample solutions for C#.
Approach taken from: Web, Cloud & Mobile Solutions with F# by Daniel Mohl.
Edit: example to clarify:
let userSorter = fun (u:users) -> u.Login
let sorted =
query { for user in dbConn.GetDataContext().Users do
sortBy ((fun (u:users) -> u.Login)(user))
select user.Login }
Basically, I want to replace the lambda by the userSorter. As it is the above code runs, but this will fail:
let userSorter = fun (u:users) -> u.Login
let sorted =
query { for user in dbConn.GetDataContext().Users do
sortBy (userSorter(user))
select user.Login }
Upvotes: 3
Views: 402
Reputation: 1480
Finally found the solution, already on Stackoverflow:
open System.Linq
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns
let runQuery (q:Expr<IQueryable<'T>>) =
match q with
| Application(Lambda(builder, Call(Some builder2, miRun, [Quote body])), queryObj) ->
query.Run(Expr.Cast<Microsoft.FSharp.Linq.QuerySource<'T, IQueryable>>(body))
| _ -> failwith "Wrong argument"
let test () =
<@ query { for p in db.Products do
where ((%predicate) p)
select p.ProductName } @>
|> runQuery
|> Seq.iter (printfn "%s")
Credits should go to Tomas Petricek, you can have my bounty!
Edit: To match against any query result of type 'T see my other Q&A
Upvotes: 3