F#中的实体框架和匿名类型

时间:2011-12-17 18:09:14

标签: entity-framework f#

尝试使用匿名类型进行查询:

let temporaryBookModel =
  query <@ context.Books 
    |> Seq.filter (fun book -> book.Id = bookId)
    |> Seq.map(fun item -> (item.Id, item.ParentUser.Id, item.ParentUser.Alias, item.Tagline, item.Title, item.Visible, item.CreatedDate))
    |> Seq.head @>

我一直在接受:

  

{“仅支持无参数构造函数和初始值设定项   LINQ to Entities。“}

如果我直接将值映射到一个类型,那将是有意义的,但是匿名类型不应该抛出这个异常我会想,因为它们基于对象初始化器功能?不幸的是,我在匿名类型上找到的任何东西似乎都说这是正确的语法。那或类似的东西:

let temporaryBookModel =
  query <@ context.Books 
    |> Seq.filter (fun book -> book.Id = bookId)
    |> Seq.map(fun item -> (("a", item.Id), ("b", item.ParentUser.Id), ("c", item.ParentUser.Alias), ("d", item.Tagline), ("e", item.Title, item.Visible), ("f", item.CreatedDate)))
    |> Seq.head @>

2 个答案:

答案 0 :(得分:3)

F#是否支持匿名类型?

据我所知 - 事实并非如此。但是有两种可行的解决方法:

  • 使用元组(正如您所使用的)
  • 使用记录类型,但在这种情况下,您需要先定义记录。这样的事情:
type Book =
    { 
        Id: int;
        ParentId: int;
        ParentAlias: string;
        TagLine: string;
        Title: string;
        Visible: bool;
        CreatedDate: DateTime;
    }

使用代码行如下所示:

...
|> Seq.map 
    (fun item -> 
        {
            Id = item.Id; 
            ParentId = item.ParentUser.Id;
            ParentAlias = item.ParentUser.Alias;
            TagLine = item.Tagline;
            Title = item.Title;
            Visible = item.Visible;
            CreatedDate = item.CreatedDate
        }) 

您可以在类似问题here

中找到更多解释

<强>更新

记录类型用法对我来说是更优雅的解决方案,但是它看起来不适用于实体框架 - F# -> Record with parameterless constructor?

所以根据Tomas Petricek的回答 - 它必须声明为显式类型,参数少于构造函数和必要的属性。

答案 1 :(得分:0)

我没有EF设置或您的模型,但是使用了新的F#4.6 Anonymous Records功能,此示例非常接近您要尝试的示例。

open System
open System.Linq

type Parent = {
    Id: int;
    Alias: string;
}

type Book = { 
    Id: int;
    ParentUser: Parent;
    Tagline: string;
    Title: string;
    Visible: bool;
    CreatedDate: DateTime }

[<EntryPoint>]
let main argv =

    let books = [| { Id = 1; ParentUser = { Id = 1; Alias = "ParentBook"; }; Tagline = "BattaBoom"; Title = "clear"; Visible = true; CreatedDate = DateTime.UtcNow }|]

    let bookId = 1

    let res = 
        books 
        |> Seq.filter (fun book -> book.Id = bookId)
        |> Seq.map(fun item -> {| Id = item.Id; ParentId = item.ParentUser.Id; ParentAlias = item.ParentUser.Alias; Tagline = item.Tagline; Title = item.Title; Visible = item.Visible; CreatedDate = item.CreatedDate |})
        |> Seq.head

    printfn "result %A" res

    0 // return an integer exit code

请注意,在匿名记录的花括号内使用|字符。这就是现在将常规记录与F#中的匿名记录区分开的地方。另外,在上面的示例中,匿名记录类型中的属性名称需要显式指定,因为与C#不同,属性名称不是基于其源属性/赋值字段而隐含的。建议在将来的语言规范中进行后续更改,以允许使用implicit property names功能。