问题描述
|
姆耶洛!目前,我正在尝试创建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#到LINQ的查询翻译器:调用
(没有,
System.Collections.Generic.IEnumerable1[WebFSharp.Entities.User]
op_PipeRight[DbSet
1,IEnumerable1](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,版本= 0.0.0.0,
文化=中立,
PublicKeyToken = null]]))))]])这是
不是有效的查询表达式。校验
允许查询的规范
并考虑移动一些查询
超出报价
这是怎么回事?是因为在将参数注入ѭ10之前会对其求值吗?
无论如何,以下代码可以工作,但灵活性较差:
member x.GetUsersByName name =
query <@ ctx.Users |> Seq.filter(fun z -> z.Name = name) @>
let service = new UserService()
service.GetUsersByName \"James\"
任何人都可以对发生的事情有所了解吗?
解决方法
在您的代码中,F#到LINQ转换器没有任何方法可以检查您指定的功能(参数
e
是某些已编译的代码-无法获得可以翻译为SQL的带引号的表示形式)。
您需要使用Expr<User -> bool>
而不是User -> bool
。这意味着,您无需传递函数,而是传递一些用作参数的代码表示形式(可以将其分析并转换为SQL):
member x.GetUsersWhere (e:Expr<User -> bool>) =
query <@ ctx.Users |> Seq.filter %e @>
注意the16ѭ语法-这意味着应将引用的代码嵌入(拼接)到主引用的表达式中,因此翻译者将其视为单个表达式。调用它时,您还需要使用引号传递该函数:
let service = new UserService()service.GetUsersWhere <@ fun z -> z.Name = \"James\" @>