.NET LINQ IQueryable:什么是`Expression`?

时间:2015-05-20 13:39:24

标签: .net linq iqueryable

我正在使用LINQ提供程序,因此我正在实现IQueryable。

此界面中Expression属性的用途是什么?我通常会从我的实现中返回类似Expression.Constant(this)的内容,但不知道这是不是很糟糕。

奇怪的是documentation状态"这允许框架区分LINQ和实体SQL查询"。

1 个答案:

答案 0 :(得分:4)

IQueryable.Expression成员被所有各种IQueryProvider"运营商"反馈给Queryable.*。 (.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) }
            ));
}

(摘自referencesource

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

如果你通过IQueryable直接传递了Expression.Constant()课程的完整参考资料,显然没有人会杀了你,但我确实认为这不是&#34;#34; kosher&#34 ;。

关注&#34;真实&#34; Expression中的表达式(就像它由Enumerable.AsQueryable(),由EF和LINQ-to-SQL完成,只是为了命名三个IQueryable提供者)是其他外部类可以自由分析和操纵Expression并以与Queryable.Where相同的方式将其反馈给提供者,这样做

Expression expression = source.Expression;
// here "expression" is manipulated
return source.Provider.CreateQuery<SomeType>(expression);

举个例子......有一些&#34;查询修复程序可以修改查询,如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();

其中FullName 不是在数据库中映射,并且属性如下:

class Employee
{
    [Computed]
    public string FullName
    {
        get { return FirstName + " " + LastName; }
    }

FirstNameLastName映射到数据库)。 DelegateDecompiler Expression获取IQueryable,搜索具有Computed属性的属性,对其进行反编译并放置反编译代码(转换为表达式树)回到IQueryable.Expression(虽然使用IQueryable.Provider.CreateQuery()

如果您想保存其他数据,可以将其放在Provider中:您可以在IQueryProvider方法中生成CreateQuery类的新实例。这也是由Queryable.*运算符反馈的(因为CreateQuery<>source.Provider的实例方法)