我只想做这样简单的事情:
context.Users.Any(fun currentUser -> currentUser.UserName = userName)其中上下文只是一个实体框架上下文。现在,当我在"currentUser“上盘旋时,它知道它是一个用户类型。不过,我得到的是:
根据此程序点之前的信息查找不确定类型的对象。在此程序点之前可能需要一个类型注释来约束对象的类型。这可能会使查找问题得到解决。
现在我意识到我可以这样做:
context.Users.Any(fun (currentUser:User) -> currentUser.UserName = userName)但是,这似乎很愚蠢,因为c#可以很容易地推断出以下类型:
context.Users.Any(currentUser => currentUser.UserName = userName)完整的方法是:
let FindAndRemoveUser(userName:String, context:StoryBoardContext) =
if context.Users.Any(fun currentUser-> currentUser.UserName = userName) then
let foundUser = context.Users.Where(fun innerUser -> innerUser.UserName = userName).First()
context.Users.DeleteObject(foundUser)
context.SaveAll() |> ignore我是否错误地认为F#应该处理类型推断,或者比C#更好?
发布于 2011-11-23 00:29:55
我认为你的方法有一个更根本的问题,而不仅仅是你描述的问题。将Where或Any与C#中的lambda表达式一起使用时,C#编译器将lambda转换为表达式树Expression<Func<_, _>>,因此LINQ实体可以将代码转换为C#查询。
但是,当您使用F# lambda函数作为参数时,它将被编译为一个函数(或者Func<_, _>类型的委托)。这意味着您的代码将调用内存中的处理函数版本,您将在内存中完成所有处理,而不是在数据库服务器上执行!
要在F# 2.0中编写查询,您需要将所有代码包装在一个引号中,并使用来自F# PowerPack的query函数运行它(F# 3.0将使它变得更好,但不幸的是,这只是一个测试版)。你可能需要这样的东西:
if query <@ context.Users |> Seq.exists (fun currentUser ->
currentUser.UserName = userName) @> then
let foundUser =
query <@ context.Users
|> Seq.filter (fun usr -> usr.UserName = userName)
|> Seq.head @>
context.Users.DeleteObject(foundUser)
context.SaveAll() |> ignore (另外,我不确定您是否需要预先检查用户是否存在-您只需要找到所有使用filter的用户,然后如果返回的序列包含什么内容,则删除第一个用户)
发布于 2011-11-22 23:24:26
我认为context.Users是一个seq<User>,所以您可以在Seq模块上使用高阶函数。与Linq相比,您将受益于F#序列中的类型推断:
let FindAndRemoveUser(userName:String, context:StoryBoardContext) =
if context.Users |> Seq.exists (fun currentUser -> currentUser.UserName = userName) then
let foundUser = context.Users |> Seq.filter (fun innerUser -> innerUser.UserName = userName) |> Seq.head
context.Users.DeleteObject(foundUser)
context.SaveAll() |> ignore在Linq和F#序列这里中有一个关于类型推断的有趣线程。
https://stackoverflow.com/questions/8235234
复制相似问题