【发布时间】:2013-08-22 19:59:40
【问题描述】:
使用IQuerayble<TItem> 时,我们可以像这样调用Select:
query.Select( item => new { A=item.Prop1, B=item.Prop2});
而Select 方法需要Expression<Func<TItem,TResult>>
我需要使用ExpandoObject 而不是匿名但静态类型的类。
如果可能的话,它看起来像:
query.Select( item => dynamic new ExpandoBoject { A=item.Prop1, B=item.Prop2});
所以我想构造表达式树Expression<Func<TItem,ExpandoObject>>,其中对象的属性以与匿名类型类似的方式初始化。
动态功能仅用于初始化,因此 Func 返回 ExpandoObject 而不是 dynamic 是可以的。
我找不到太多关于 Expression.Dynamic 和我应该使用的相应活页夹的文档。
更新 1
为什么我需要所有这些东西?
因为我想get primary keys.
我想对任何实体类型都这样做。
我知道如何获取组成 PK 的属性列表,但现在我需要将实体投影到EntityKey。好吧,可能是这个类的相同等价物。
var keys = context.Set<TEntity>().Where(Expression<Func<TEntity,bool>).Select(Expression<Func<TEntity,EntityKey>>);
正如我在 cmets 中指出的,包含块的 lambda 不能转换为表达式树,所以我不能简单地创建字典并填充它。现在我正在使用语义上接近此代码的表达式树:
var dict = new Dictionary<string,object>();
dict.Add("Prop1",value1);
dict.Add("Prop2",value2);
return dict
但我怀疑 EF 能否解析包含块的表达式。需要检查。
而且我很好奇它是否可以与动态对象和 Expression.MemberInit 一起使用,因为它可以与静态对象一起使用。
更新 2
实体框架不支持字典初始化语法。
它会抛出 NotSupportedException 消息:LINQ to Entities 中仅支持具有单个元素的列表初始化项。
更新 3
EF 也不支持块表达式。NotSupportedException 带有消息:“块”类型的未知 LINQ 表达式。
【问题讨论】:
-
你不能做类似这样的事情:
query.Select( item => dynamic new ExpandoBoject { A=item.Prop1, B=item.Prop2});Lippert 告诉它:stackoverflow.com/questions/7478048/…。 -
我知道,我不能。这是一个打算用动态构建表达式树的例子。
-
可以做的是在 LINQ 中创建一个匿名类型,然后在 IQueryable 完成后,在 IEnumerable 部分中将匿名类型复制到 Expando 对象。显然,这两个表达式都可以通过某种方式自动生成。
-
现在请记住一点不同的方法。我已经实现了自己的 EntityKey 类,它实现了 IEquatable 和 IDictionary
接口。对于每个实体,我可以生成具有与 PK 相对应的属性的后代,而 PK 只需写入字典即可。但我很感兴趣是否可以避免代码生成。
标签: c# .net dynamic expression-trees iqueryable