带谓词的查询函数

时间:2011-05-24 13:59:14

标签: f#

Mjello在那里!我正在尝试创建一个F#应用程序,现在我已经打了另一面墙。

问题出现在Microsoft.FSharp.Linq.Query模块中,query函数在那里不接受我的谓词,如果它们作为参数传递。看看这个:

member x.GetUsersWhere (e:User -> bool) =
    query <@ ctx.Users |> Seq.filter e @>

然后我称之为:

let service = new UserService()
service.GetUsersWhere (fun z -> z.Name = "James")
那应该没问题呃?好吧,编译器同意:

  

使用以下构造   查询但未被识别   F#-to-LINQ查询翻译:调用   (没有,        System.Collections.Generic.IEnumerable 1[WebFSharp.Entities.User] op_PipeRight[DbSet 1,IEnumerable的1](System.Data.Entity.DbSet 1 [WebFSharp.Entities.User]   Microsoft.FSharp.Core.FSharpFunc 2[System.Data.Entity.DbSet 1 [WebFSharp.Entities.User],System.Collections.Generic.IEnumerable 1[WebFSharp.Entities.User]]), [PropertyGet (Some (FieldGet (Some (Value (WebFSharp.Business.UserService)), WebFSharp.Business.MyContext ctx)), System.Data.Entity.DbSet 1 [WebFSharp.Entities.User]   用户,                      []),         设(谓词,值(),              Lambda(来源,                      致电(无,                            System.Collections.Generic.IEnumerable 1[WebFSharp.Entities.User] Filter[User](Microsoft.FSharp.Core.FSharpFunc 2 [WebFSharp.Entities.User,System.Boolean]   System.Collections.Generic.IEnumerable 1[WebFSharp.Entities.User]), [predicate, Coerce (source, System.Collections.Generic.IEnumerable 1 [[WebFSharp.Entities.User,   WebFSharp.Entities,Version = 0.0.0.0,   文化=中性,   PublicKeyToken = null]])])))])这是   不是有效的查询表达式。校验   允许查询的规范   并考虑移动一些查询   超出报价

怎么回事?是因为在将参数注入其中之前会评估Expr吗?

无论如何,以下代码有效,但不太灵活:

member x.GetUsersByName name =
    query <@ ctx.Users |> Seq.filter(fun z -> z.Name = name) @>

let service = new UserService()
service.GetUsersByName "James"

有人可以对正在发生的事情有所了解吗?

1 个答案:

答案 0 :(得分:8)

在你的代码中,F#到LINQ转换器没有任何方法来检查你指定的函数(参数e是一些编译代码 - 没有办法得到它的引用表示可能是翻译成SQL)。

您需要使用Expr<User -> bool>代替User -> bool。这意味着您不会传递函数,而是传递一些用作参数的代码(可以分析并转换为SQL):

member x.GetUsersWhere (e:Expr<User -> bool>) = 
    query <@ ctx.Users |> Seq.filter %e @>

请注意%e语法 - 这意味着引用的代码应嵌入(拼接)到主引用表达式中,因此转换程序将其视为单个表达式。调用它时,您还需要使用引号传递函数:

let service = new UserService()service.GetUsersWhere <@ fun z -> z.Name = "James" @>