-
Notifications
You must be signed in to change notification settings - Fork 854
Labels
Area-QueriesQuery expressions and library implementationQuery expressions and library implementationBugImpact-Low(Internal MS Team use only) Describes an issue with limited impact on existing code.(Internal MS Team use only) Describes an issue with limited impact on existing code.
Milestone
Description
When projecting an anonymous record on IQueryable the generated tree contains a Delegate.Invoke for the anonymous type constructor, this causes some parsers/drivers to be unable to understand the operation (eg. Entity Framework)
This looks to happen when accessing deep members and having long record member names.
Repro steps
Provide the steps required to reproduce the problem:
open System
open System.Linq
type Person = { Name: string; Id : int }
type Wrapper = { Person: Person }
let data = [
{ Person = { Name = "One"; Id = 1 } }
{ Person = { Name = "Two"; Id = 2 } }
{ Person = { Name = "Three"; Id = 3 } }
]
let queryWithInvoke =
data
.AsQueryable()
.Select(fun x -> {| Other = {| Name = x.Person.Name; Id = x.Person.Id |} |})
// short label names do not generate an invoke call
let queryWithoutInvoke =
data
.AsQueryable()
.Select(fun x -> {| Other = {| A = x.Person.Name; B = x.Person.Id |} |})
printfn "%A" queryWithInvoke.Expression;
printfn "------"
printfn "%A" queryWithoutInvoke.ExpressionOutputs:
[{ Person = { Name = "One"
Id = 9a093c1d-9a3c-4366-806e-7c32b4388a1d }
Value = 0 }; { Person = { Name = "Two"
Id = ded2fd37-69cd-4d56-bc05-69e539264301 }
Value = 1 }; { Person = { Name = "Three"
Id = 798c98fb-a772-4911-84cc-63101b369cb9 }
Value = 2 }].Select(x => new <>f__AnonymousType1021199106`1(Name => new <>f__AnonymousType3987781292`2(x.Person.Id, Name).Invoke(x.Person.Name)))
------
[{ Person = { Name = "One"
Id = 9a093c1d-9a3c-4366-806e-7c32b4388a1d }
Value = 0 }; { Person = { Name = "Two"
Id = ded2fd37-69cd-4d56-bc05-69e539264301 }
Value = 1 }; { Person = { Name = "Three"
Id = 798c98fb-a772-4911-84cc-63101b369cb9 }
Value = 2 }].Select(x => new <>f__AnonymousType1021199106`1(new <>f__AnonymousType2589797714`2(x.Person.Name, x.Person.Id)))The problem is:
new <>f__AnonymousType1021199106`1(
Name => new <>f__AnonymousType3987781292`2(
x.Person.Id, Name
)
.Invoke(x.Person.Name)) // <- hereThe first case generates a plain constructor, and the second injects an IIFE for Person.Name which causes inconsistency in query parsing
from: fsharp/fslang-suggestions#1249
Expected behavior
No difference between the expressions
Actual behavior
Delegate invocation inside the expression
Known workarounds
Use small record labels
Related information
- Windows 11 / MacOs / Arch Linux
- .NET6
- Editing Tools (any)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Area-QueriesQuery expressions and library implementationQuery expressions and library implementationBugImpact-Low(Internal MS Team use only) Describes an issue with limited impact on existing code.(Internal MS Team use only) Describes an issue with limited impact on existing code.