EntityFramework和表达式翻译

时间:2015-06-11 08:45:20

标签: entity-framework linq-expressions

我有一个实体类Foo我已经部分包含以下代码

private readonly static Expression<Func<Foo, int>> MyKeyExpression = (x) => x.Key;

public int MyKey
{
   get { return MyKeyExpression.Compile()(this); }
}

以上的工作原理我在EntityFrameworks linq查询中可以使用MyKey

为什么不做以下工作?

private readonly static Expression<Func<Foo, int>> MyKeyExpression = (x) => x.Key;

// Set in the constructor with
// _myKeyDelegate = MyKeyExpression.Compile();
private readonly Func<Foo,int> _myKeyDelegate;

public int MyKey
{
   get { return _myKeyDelegate(this); }
}

我理解委托和表达式之间的区别(或者我可能不这样做?)但是对于EntityFramework如何能够以不同方式解释属性感到困惑,因为MyKeyExpression.Compile()只返回该委托,然后调用返回INT。也许我对编译器实际处理C#属性的方式缺乏了解?

第一个示例有效的用法示例,但第二个示例抛出了一个关于无法将其转换为SQL的异常。:

dbContext.Foo.Delete(x => x.MyKey == 5)

2 个答案:

答案 0 :(得分:1)

我会说你不完全理解代表和表达之间的区别。

Delegate是对编译成IL的代码的引用。只有你可以使用它在.net CLR中执行它。

表达式对象是一个表示为树的表达式(您可以想到AST)。您可以将其编译为IL(编译方法),也可以检查它并为其他执行环境生成代码,例如编写到SQL(这是EF的功能)。

当C#编译器编译代码时,首先构建语法树然后编译它。基本上表达式是第一部分没有第二部分的结果,因此您可以使用SQL转换器将其编译为SQL。或者您可以自己编写并将其翻译成其他任何内容。

答案 1 :(得分:0)

你说的很奇怪...... EF忽略getter的内容和映射属性的设置者(MyKey)。

应该使用基于MyKey的WHERE子句生成查询,而不管getter做什么。

你是如何映射MyKey属性的?缺少setter,因此EF不会在DB表上生成字段,也不会自动映射它。