问题
Trying to get a query with an anonymous type working:
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 @>
And I keep getting:
{"Only parameterless constructors and initializers are supported in LINQ to Entities."}
Which would make sense if I were mapping the values to a type directly, but anonymous types shouldn't throw this exception I would think since they are based on the object initializer functionality? Unfortunately anything I found on anonymous types seem to say this is the correct syntax. That or something like this:
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 @>
回答1:
Does F# supports anonymous types?
As I know - it doesn't. But there are 2 possible ways for workarounds:
- use tuples (as you're using)
- use record types, but in this case you'll need to define record before. Something like this:
type Book =
{
Id: int;
ParentId: int;
ParentAlias: string;
TagLine: string;
Title: string;
Visible: bool;
CreatedDate: DateTime;
}
And usage code line will looks like:
...
|> 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
})
More explanations you can find in similar question here
Update:
Record types usage as for me is more elegant solution, BUT it looks like it doesn't not work with Entity Framework - F# -> Record with parameterless constructor?.
So according to Tomas Petricek answer - it has to be declared explicit type with parameters less constructor and necessary properties.
回答2:
I don't have EF setup or your model but using the new F# 4.6 Anonymous Records feature this example which is very close to what you were attempting should work.
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
Notice the use of the |
character on the insides of the curly braces of the anonymous record. This is what now distinguishes regular records from anonymous records in F#. Additionally in the example above notice that the property names in the Anonymous Record type need to be specified explicitly as unlike in C# the property names are not implicit based on their source property/field from the assignment. The feature to allow for implicit property names is suggested as a followup change in future language specifications.
来源:https://stackoverflow.com/questions/8546823/entity-framework-and-anonymous-types-in-f