linq和可能的实体框架的F#类型推理问题

时间:2011-11-22 23:12:24

标签: f# type-inference

尝试做一些像这样简单的事情:

context.Users.Any(fun currentUser -> currentUser.UserName = userName)

Context只是一个实体框架上下文。现在,当我将鼠标悬停在“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#更好还是错误的吗?

2 个答案:

答案 0 :(得分:4)

我认为您的方法比您描述的问题更具根本性。当您在C#中将WhereAny与lambda表达式一起使用时,C#编译器会将lambda转换为表达式树Expression<Func<_, _>>,因此LINQ to Entities可以将代码转换为SQL查询。

但是,当您使用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查找所有用户,然后如果返回的序列包含某些内容则删除第一个用户)

答案 1 :(得分:2)

我认为context.Usersseq<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#序列here中有一个关于类型推断的有趣线程。