是否有一个简单的实现即可在通用F#查询中使用谓词函数 [英] Is there an easy implementation to use a predicate function in a generic F# query
问题描述
我想使用通用查询功能,例如:
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 }
其中f应该是谓词函数.显然,这不能转换为sql查询.但是是否有解决此问题的方法.我已经看到了C#的示例解决方案.
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#.
方法来自:Web,Cloud& Daniel Mohl的F#移动解决方案.
Approach taken from: Web, Cloud & Mobile Solutions with F# by Daniel Mohl.
要澄清的示例:
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 }
基本上,我想用userSorter代替lambda.因为上面的代码正在运行,但这将失败:
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 }
推荐答案
终于找到了已经在Stackoverflow上的解决方案:
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")
应归功于Tomas Petricek,您可以得到我的赏金!
Credits should go to Tomas Petricek, you can have my bounty!
要与"T"类型的任何查询结果匹配,请参阅我的其他 Q&A
To match against any query result of type 'T see my other Q&A
这篇关于是否有一个简单的实现即可在通用F#查询中使用谓词函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!