Reputation: 9377
Alright... this question is more or less related to one I've asked earlier today (F# - "Not a valid property expression"), which @Tomas Petricek answer perfectly - however it seems my lack of knowledge and the DLR, requires me to ask once again (been trying for quite a while to mix something up without luck at all).
I'm having this function (stolen from the example Tomas gave in the previous thread):
let hasSeq (e:Expr<'a -> seq<'b>>) =
match e with
| Patterns.Lambda(v, Patterns.PropertyGet(Some instance, propInfo, [])) ->
printfn "Get property %s of %A" propInfo.Name instance
// TODO: Use 'Expr.Lambda' & 'Expr.PropGet' to construct
// an expression tree in the expected format
| _ -> failwith "Not a lambda!"
How would I reconstruct the expression tree with Expr.Lambda
and Expr.PropGet
? - I need to make the seq<'b>
to ICollection<'b>
instead, so that the expression in the end is like: 'a -> ICollection<'b>
Upvotes: 0
Views: 580
Reputation: 16782
Well, if you've already decomposed quotation, then maybe you can create required expression tree by yourself without ToLinqExpression
from PowerPack?
type A =
member this.Values : int[] = failwith ""
open Microsoft.FSharp.Quotations
type F<'T, 'R> = System.Func<'T, 'R>
type E = System.Linq.Expressions.Expression
type IC<'T> = System.Collections.Generic.ICollection<'T>
let toLinqPropGet (e : Expr<'T -> #seq<'R>>) =
match e with
| Patterns.Lambda(_, Patterns.PropertyGet(Some _, pi, []))
when typeof<IC<'R>>.IsAssignableFrom(pi.PropertyType) ->
let p = E.Parameter(typeof<'T>)
let propGet = E.Property(p :> E, pi)
E.Lambda<F<'T, IC<'R>>>(propGet, p) :> E
| _ -> failwith "PropGet expected"
let r = toLinqPropGet <@ fun (x : A) -> x.Values @>
printfn "%A" r
Upvotes: 3
Reputation: 243051
This isn't going to work.
You want to build a quotation of type Entity -> ICollection<Something>
and you have a quotation of type Entity -> seq<Something>
. However, entity framework only supports simple lambda functions that get some property (e.g. x => x.SomeProperty
).
If your Entity
has only a property Foo
of type seq<Something>
, then there is no way you could build a quotation with the required structure (lambda that just gets a property) and of the required type (Entity -> ICollection<Something>
), because the type of the property doesn't match!
What I suggested earlier is to change the entity to also have a property FooInternal
of the right type (ICollection<Something>
). Then you could build a quotation x => x.FooInternal
, which would work fine with entity framework.
Perhaps you could give more details about what you're actually trying to achieve? We can try to help with technical details, but it seems that you may need to adjust your design a bit (to actually work with the ICollection
type as required by EF).
Upvotes: 1