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.FSharpFunc2[System.Data.Entity.DbSet
1 [WebFSharp.Entities.User],System.Collections.Generic.IEnumerable1[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.IEnumerable1[WebFSharp.Entities.User] Filter[User](Microsoft.FSharp.Core.FSharpFunc
2 [WebFSharp.Entities.User,System.Boolean] System.Collections.Generic.IEnumerable1[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"
有人可以对正在发生的事情有所了解吗?
答案 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" @>