当我在我们的应用程序中将表达式编写为 lambda 表达式时,我通常可以使用以下结构1:
dbContext.Contents<MyEntity>()
(dbContext
属于自定义类。)
Linq1Entities/Entity Framework 以某种方式理解这意味着我正在从匹配 MyEntity
的表中SELECT
ing 项目。
现在,我正在通过 System.Linq.Expressions
类构造一个表达式。
我试图像这样复制上面的片段:
Expression.Call(Expression.Constant(dbContext), contentsMethod)
contentsMethod
之前已经通过反射的方式初始化为合适的MethodInfo
。
不幸的是,这不起作用。
Entity Framework 提示它无法将 dbContext
对象转换为 SQL。
我构建了一个我想要的类似表达式作为 lambda 表达式,并在调试器中查看了生成的表达式树。
有趣的是,常量,dbContext
被建模为似乎是闭包对象的成员访问
。
这是为什么?为什么局部变量 dbContext
由成员访问表达式中的闭包表示,为什么它不能作为常量值工作?在我的案例中,dbContext
是封闭方法的参数是否重要?
我的问题不是如何解决问题。 我已经这样做了,将上面显示的片段作为一个额外的 lambda 表达式引入,其主体与我手动构建的表达式相关联。
1:该片段如何使用的示例是以下表达式:
dbContext.Contents<MyEntity1>().Where(e1 => dbContext.Contents<MyEntity2>().Any(e2 => e1.Name == e2.Key))
最佳答案
dbContext
被建模为对闭包对象的访问,因为定义它的 lambda 正在关闭该变量。它没有使用常量值,而是关闭了另一个值,所以这就是它在 Expression
中表示的内容。如果它做了任何其他事情,它就不能正确地表示 lambda。
当 EF 说它不能将 Expression
转换为 SQL 时,它只是说代码的作者没有预料到给定的表达式,也没有创建该模式的映射到 SQL;他们根本没有预料到人们会这样做(或者不知道如何将其映射到 SQL,或者不能,或者没有时间添加该功能,无论如何)。
关于c# - 为什么必须将变量值建模为对表达式树中闭包的成员访问?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44025703/