我正在开发 LINQ 提供程序,因此正在实现 IQueryable。
此接口(interface)中 Expression
属性的用途是什么?我通常只是从我的实现中返回类似 Expression.Constant(this)
的东西,但不知道这是否不好。
奇怪的是documentation声明“这允许框架区分 LINQ 和 Entity SQL 查询”。
最佳答案
IQueryable.Expression
成员(member)被反馈到IQueryProvider
通过各种Queryable.*
“运算符(operator)”( .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()
上课,但我确实认为这不是“犹太洁食”。
将“真实”表达式放在 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);
举个例子...有一些“查询修复器”修改查询,如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; }
}
(FirstName
和 LastName
映射到数据库)。 DelegateDecompiler 接受 Expression
来自 IQueryable
, 搜索具有 Computed
的属性属性,反编译它们并将反编译代码(转换为表达式树)放回 IQueryable.Expression
(尽管使用 IQueryable.Provider.CreateQuery()
)
如果你想保存额外的数据,你可以把它放在Provider
中:您可以生成 IQueryProvider
的新实例CreateQuery
中的类方法。这也由 Queryable.*
反馈运算符(因为 CreateQuery<>
是 source.Provider
的实例方法)
关于.NET LINQ IQueryable : what is `Expression` for?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30351396/