When working with IQuerayble<TItem>
we can call Select
like this:
query.Select( item => new { A=item.Prop1, B=item.Prop2});
And Select
method expects Expression<Func<TItem,TResult>>
I need to use ExpandoObject
instead of anonymous but statically typed class.
If it were possible it would look like:
query.Select( item => dynamic new ExpandoBoject { A=item.Prop1, B=item.Prop2});
So I want to construct expression tree Expression<Func<TItem,ExpandoObject>>
where object's properties are initialized in the similar way as with anonymous type.
Dynamic functionality is only needed for initialization so it's ok that Func returns ExpandoObject
instead of dynamic
.
I cannot find much documentation about Expression.Dynamic
and corresponding binders I should use.
Update 1
Why do I need all this stuff?
Because I want to get primary keys.
I want to do it for any entity type.
I know how to get the list of the properties composing PK, but now I need to make a tricky projection of the entity to EntityKey
. Well, may be to same equvalent of this class.
var keys = context.Set<TEntity>().Where(Expression<Func<TEntity,bool>).Select(Expression<Func<TEntity,EntityKey>>);
As I noted in the comments lambdas containing blocks cannot be converted to expression trees so i cannot simple create the dictionary and fill it. Now I'm playing with the expression tree semantically close to this code:
var dict = new Dictionary<string,object>();
dict.Add("Prop1",value1);
dict.Add("Prop2",value2);
return dict
But I doubt EF can parse the expression containing blocks. Need to check.
And I'm curious whether it will work with dynamic objects and Expression.MemberInit as it works with static objects.
Update 2
Entity Framework does not support dictionary initialization syntax.
It throws NotSupportedException
with the message: Only list initializer items with a single element are supported in LINQ to Entities.
Update 3
EF does not support block expressions aswell.NotSupportedException
with message: Unknown LINQ expression of type 'Block'.
Now I'm playing with the expression tree semantically close to this code:
var dict = new Dictionary<string,object>(); dict.Add("Prop1",value1); dict.Add("Prop2",value2); return dict;
You can do that, because you can write that code as as a single expression like this:
new Dictionary<string, object>
{
{ "Prop1", value1 },
{ "Prop2", value2 }
};
And you can create an expression tree that contains this expression (which EF should be able to handle) like this:
var addMethod = typeof(Dictionary<string, object>).GetMethod("Add");
var expression = Expression.Lambda<Func<Dictionary<string, object>>>(
Expression.ListInit(
Expression.New(typeof(Dictionary<string, object>)),
Expression.ElementInit(
addMethod,
Expression.Constant("Prop1"),
value1Expression),
Expression.ElementInit(
addMethod,
Expression.Constant("Prop2"),
value2Expression)),
itemParameterExpression);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With