.NET LINQ IQueryable:“表达式”的用途是什么?

Ian*_*son 3 .net linq iqueryable

我正在开发 LINQ 提供程序,因此正在实现 IQueryable。

该接口中的属性的用途是什么Expression?我通常只是Expression.Constant(this)从我的实现中返回类似的东西,但不知道这是否不好。

奇怪的是,文档指出“这允许框架区分 LINQ 和 Entity SQL 查询”。

xan*_*tos 5

该成员由所有各种“操作员”(、、 、 ...)IQueryable.Expression反馈给,例如:IQueryProviderQueryable.*.Where().Select().Join()

public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate) {
    if (source == null)
        throw Error.ArgumentNull("source");
    if (predicate == null)
        throw Error.ArgumentNull("predicate");
    return source.Provider.CreateQuery<TSource>( 
        Expression.Call(
            null,
            ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), 
            new Expression[] { source.Expression, Expression.Quote(predicate) }
            ));
}
Run Code Online (Sandbox Code Playgroud)

(取自参考资料来源

通常它应该是整个表达式。

显然,如果您通过 直接传递对您的IQueryable类的完整引用Expression.Constant(),没有人会杀死您,但我确实认为这不是“犹太洁食”。

将“真实”表达式放入Expression(就像由 、 EF 和 LINQ-to-SQL 完成的那样Enumerable.AsQueryable(),仅举三个IQueryable提供程序)是其他外部类可以自由地分析和操作Expression并将其反馈给提供者以与提供者相同的方式Queryable.Where这样做

Expression expression = source.Expression;
// here "expression" is manipulated
return source.Provider.CreateQuery<SomeType>(expression);
Run Code Online (Sandbox Code Playgroud)

举个例子......有一些“查询修复程序”可以修改查询,例如https://github.com/davidfowl/QueryInterceptor(查询的通用修饰符)或https://github.com/hazzik/ DelegateDecompiler,允许执行以下操作:

var employees = (from employee in db.Employees
                 where employee.FullName == "Test User"
                 select employee).Decompile().ToList();
Run Code Online (Sandbox Code Playgroud)

whereFullName 映射到数据库中,并且是如下属性:

class Employee
{
    [Computed]
    public string FullName
    {
        get { return FirstName + " " + LastName; }
    }
Run Code Online (Sandbox Code Playgroud)

(与FirstNameLastName映射到数据库)。DelegateDecompilerExpression从 中获取IQueryable,搜索具有该Computed属性的属性,对其进行反编译,并将反编译代码(转换为表达式树)放回到 中IQueryable.Expression(尽管使用IQueryable.Provider.CreateQuery()

如果你想保存额外的数据,你可以把它放在:你可以在方法中Provider生成类的新实例。这也是由操作员反馈的(因为是 的实例方法)IQueryProviderCreateQueryQueryable.*CreateQuery<>source.Provider