LINQ to SQL如何知道委托中的内容?

Pab*_*ney 4 c# linq-to-entities entity-framework linq-to-sql

使用实体框架,我们可以:

MyContext context = ... // a normal EF context 

var products =  context.Products.Where(p => p.Location == "France") ; 
Run Code Online (Sandbox Code Playgroud)

要么

var products =  context.Products.Where(p => p.CategoryId == 54) ;
Run Code Online (Sandbox Code Playgroud)

哪些都在它们的等效SQL查询中进行转换.

好的,但在那里的某个地方,有一段代码处理这个:

public static IEnumerable<T> Where(Func<bool, T> func) {
     ......
}
Run Code Online (Sandbox Code Playgroud)

从那个Where功能,怎么LINQ to SQL知道实现的是func什么?

答案可能很明显,但我找不到它.

xan*_*tos 6

你应该真正对你的代码做一个转到定义.该函数用于LINQ到SQL和实体框架是

IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
Run Code Online (Sandbox Code Playgroud)

包含在使用表达式树System.Linq.Queryable中,表达式树是一个能够"描述"代码片段的构造.一个小小的引用:

表达式树表示树状数据结构中的代码,其中每个节点是表达式,例如,方法调用或二进制操作,例如x <y.

例如,你的第一个表达式

var products = context.Products.Where(p => p.Location == "France"); 
Run Code Online (Sandbox Code Playgroud)

由C#编译器转换为此代码:

ParameterExpression par = Expression.Parameter(typeof(Product), "p");
LambdaExpression lambda = Expression.Lambda(
    Expression.Equal(
        Expression.Property(par, "Location"), 
        Expression.Constant("France")), 
    par);

var products = context.Products.Where(lambda); 
Run Code Online (Sandbox Code Playgroud)

现在......虽然表达式树的创建非常简单,但反向操作(解构表达式树和创建查询)非常复杂.大头痛复杂.几乎神奇的复杂程度:-)

问题不在于解构表达式树.这很容易.您使用ExpressionVisitor就完成了.问题是合并LINQ查询的各个层并理解程序员想要获得的内容.

我将补充说IL(.NET的"程序集")足够高,可以对其进行反编译(例如参见IlSpy).至少有一个库,DelegateDecompiler能够将委托反编译为表达式树,因此即使没有表达式树,LINQ-to-SQL和EF也可以使用类似的和反编译的方法直接使用SQL语言.