EntityFramework and Expressions translation

888 views Asked by At

I have a entity class Foo I've made partial containing the following code

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

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

The above works as in I can use MyKey in EntityFrameworks linq queries.

Why don't the following work?

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); }
}

I understand the difference between a delegate and an expression(or maybe i don't?) but is confused how EntityFramework is able to interpret the property differently since MyKeyExpression.Compile() returns just that delegate which is then invoked returning an int. Perhaps its my lack of understanding of how the compiler actually handles C# Properties?

Example of usage where first example works but second examples throw a exception about not being able to translate it to SQL.:

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

There are 2 answers

3
Andrey On BEST ANSWER

I would say you don't fully understand difference between delegates and expressions.

Delegate is a reference to code compiled into IL. Only thing you can with it is execute it within .net CLR.

Expression object is a expression represented as tree, (you can think of AST). You can compile it to IL (Compile method) or you can inspect it and generate code for other execution environment, for example into SQL (that's what EF does).

When C# compiler compiles code, first it builds syntax tree and then compiles it. Basically expression is result of first part without second, so you could use SQL translator to compile it to SQL. Or you can write you own and translate it to anything else.

4
bubi On

It's very strange what you are saying... EF ignores the content of the getter and the setter of a mapped property (MyKey).

The query should be generated with a WHERE clause based on MyKey independent of what getter does.

How did you map the MyKey property? There is the setter missing so EF does not generate a field on the DB table and does not map it automatically.