2011-05-24 73 views
1

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") 

这应该是罚款吧?那么,编译器dosent同意:

下面的结构是在 查询使用,但不被 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(source, 调用(无, 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,版本= 0.0.0.0, 文化=中立, PublicKeyToken =空]])])))])这是 不是有效的查询表达式。检查 允许的查询规范 ,并考虑将一些查询 出报价

的怎么回事?是否因为Expr将在参数注入之前进行评估?

不管怎样,下面的代码的作品,但没有那么灵活:

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

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

任何人都可以请棚刚刚发生一些轻?

回答

8

在您的代码中,F#to 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" @>