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()
, но я думаю, что это не «кошер».
Точка ввода «реального» выражение в 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);
чтобы дать пример ... Есть некоторые «запрос закрепитель» s, что изменить запрос, как 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
)
Попробуйте посмотреть, что присутствует в EF или LINQ-to-SQL в этой собственности ... – xanatos
Как я помню, 'Expression' собственности содержит выражение для текущего 'IQueryable', поскольку мы можем иметь цепочку из них, поэтому каждый' IQueryable' имеет свои собственные и ранее сгруппированные выражения. Но я могу ошибаться, поскольку я использую это давно. –
@SergeyLitvinov Да, я знаю, что это один из возможных способов его использования, но насколько я знаю, нет необходимости в том, чтобы инфраструктура использовала его таким образом. Так ли это свойство для разработчиков, как им нравится? –