【发布时间】:2017-05-17 13:02:55
【问题描述】:
当我在我们的应用程序中将表达式编写为 lambda 表达式时,我通常可以使用以下构造1:
dbContext.Contents<MyEntity>()
(dbContext 属于自定义类。)
不知何故,Linq1Entities/Entity Framework 理解这意味着我是 SELECTing 表中匹配 MyEntity 的项目。
现在,我正在通过 System.Linq.Expressions 类构造一个表达式。
我试图像这样复制上面的片段:
Expression.Call(Expression.Constant(dbContext), contentsMethod)
contentsMethod之前已经通过反射的方式初始化为合适的MethodInfo。
很遗憾,这不起作用。
实体框架抱怨它无法将dbContext 对象转换为 SQL。
我已经构建了一个与我想要的 lambda 表达式类似的表达式,并在调试器中查看了生成的表达式树。
有趣的是,dbContext 不是常量,而是被建模为似乎是闭包对象的member access。
这是为什么呢?为什么局部变量 dbContext 由成员访问表达式中的闭包表示,为什么它不作为常量值工作?在我的情况下,dbContext 是封闭方法的参数是否重要?
我的问题是不是如何解决这个问题。 我已经这样做了,将上面显示的片段作为一个额外的 lambda 表达式引入,它的主体与我手动构建的表达式相关联。
1:如何使用该片段的一个示例是以下表达式:
dbContext.Contents<MyEntity1>().Where(e1 => dbContext.Contents<MyEntity2>().Any(e2 => e1.Name == e2.Key))
【问题讨论】:
-
dbContext 是一个由不同表组成的数据库对象。 A Select 查询表。这些表由具有不同数据类型的列组成。通常转换发生在列的字段类型上。
-
你能举一个更完整的例子来说明你如何使用
dbContext.Contents<MyEntity>()吗?问题似乎很不清楚,至少对我来说。我知道你有 dbContext 参数,你将它传递给一些 lambda,它被捕获并且它的访问变成了闭包对象的成员访问。 -
@Evk:我添加了一个脚注,其中包含一个简短且匿名但完整的表达式,其中包含指示的片段。
-
我实际上无法重现这个。我使用
Expression.Constant(dbContext)(确切地说是Expression.PropertyOrField(Expression.Constant(dbContext), "NameOfMyDbSetProperty")))构建了一个表达式,代表您的确切Any查询,它可以正常工作而不会受到EF 方面的抱怨。 -
@Evk 实际上它适用于属性/字段,但不适用于方法调用(肯定适用于像
Set<T>这样的通用实例方法)
标签: c# entity-framework linq lambda linq-expressions