LINQ to SQL 如何知道委托中有什么?
How does LINQ to SQL know what's inside a delegate?
有了 entity framework,我们可以做到:
MyContext context = ... // a normal EF context
var products = context.Products.Where(p => p.Location == "France") ;
或
var products = context.Products.Where(p => p.CategoryId == 54) ;
它们都在等效的 SQL 查询中翻译。
好的,但是在那边的某个地方,有一段代码可以处理这个问题:
public static IEnumerable<T> Where(Func<bool, T> func) {
......
}
从那个 Where
函数,LINQ to SQL
怎么知道 func
的实现是什么?
也许是显而易见的答案,但我真的找不到。
您真的应该对您的代码执行 Go To Definition。用于 LINQ-to-SQL 和 Entity Framework 的 function 是
IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
包含在System.Linq.Queryable that uses expression trees中,这是一个能够"describe"段代码的结构。一点引述:
Expression trees represent code in a tree-like data structure, where each node is an expression, for example, a method call or a binary operation such as x < y.
例如,您的第一个表达式
var products = context.Products.Where(p => p.Location == "France");
由 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);
现在...虽然创建表达式树非常简单,但反向操作(取消构建表达式树并创建查询)却非常复杂。大大复杂的头疼。近乎魔法级的情结:-)
问题不在于取消构建表达式树。那很容易。您使用 ExpressionVisitor 就完成了。问题是合并 LINQ 查询的各个层并理解程序员想要获得的内容。
我要补充一点,IL(.NET 的 "assembly")级别足够高,可以对其进行反编译(例如,参见 IlSpy). There is at least a library, DelegateDecompiler,它能够将委托反编译为一个表达式树,所以即使没有表达式树,LINQ-to-SQL 和 EF 也可以使用类似的方法和反编译方法直接用于 SQL 语言。
有了 entity framework,我们可以做到:
MyContext context = ... // a normal EF context
var products = context.Products.Where(p => p.Location == "France") ;
或
var products = context.Products.Where(p => p.CategoryId == 54) ;
它们都在等效的 SQL 查询中翻译。
好的,但是在那边的某个地方,有一段代码可以处理这个问题:
public static IEnumerable<T> Where(Func<bool, T> func) {
......
}
从那个 Where
函数,LINQ to SQL
怎么知道 func
的实现是什么?
也许是显而易见的答案,但我真的找不到。
您真的应该对您的代码执行 Go To Definition。用于 LINQ-to-SQL 和 Entity Framework 的 function 是
IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
包含在System.Linq.Queryable that uses expression trees中,这是一个能够"describe"段代码的结构。一点引述:
Expression trees represent code in a tree-like data structure, where each node is an expression, for example, a method call or a binary operation such as x < y.
例如,您的第一个表达式
var products = context.Products.Where(p => p.Location == "France");
由 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);
现在...虽然创建表达式树非常简单,但反向操作(取消构建表达式树并创建查询)却非常复杂。大大复杂的头疼。近乎魔法级的情结:-)
问题不在于取消构建表达式树。那很容易。您使用 ExpressionVisitor 就完成了。问题是合并 LINQ 查询的各个层并理解程序员想要获得的内容。
我要补充一点,IL(.NET 的 "assembly")级别足够高,可以对其进行反编译(例如,参见 IlSpy). There is at least a library, DelegateDecompiler,它能够将委托反编译为一个表达式树,所以即使没有表达式树,LINQ-to-SQL 和 EF 也可以使用类似的方法和反编译方法直接用于 SQL 语言。