【问题标题】:Entity Framework and Anonymous Types in F#F# 中的实体框架和匿名类型
【发布时间】:2011-12-17 18:09:13
【问题描述】:

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

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 @>

【问题讨论】:

  • F# 没有“匿名类型”的概念——这是 C# 的一个特性。在这里,您正在构建普通元组。
  • 您是否尝试将错误隔离到更具体的构造(即首先尝试 Seq.map (fun i -> i.Id)、Seq.map (fun i -> i.Id、 i.Id)) 等?

标签: entity-framework f#


【解决方案1】:

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 的回答 - 它必须被声明为显式类型,带有更少的构造函数和必要的属性。

【讨论】:

    【解决方案2】:

    我没有 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 的功能作为未来语言规范的后续更改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-19
      • 1970-01-01
      • 1970-01-01
      • 2015-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-29
      相关资源
      最近更新 更多