Instrukcje: Używanie drzew wyrażeń do kompilowania zapytań dynamicznych (C#)How to: Use Expression Trees to Build Dynamic Queries (C#)

W programie LINQ, drzew wyrażeń są używane do reprezentowania strukturyzowanych zapytań, których platformą docelową źródeł danych, który implementuje IQueryable<T>.In LINQ, expression trees are used to represent structured queries that target sources of data that implement IQueryable<T>. Na przykład implementuje dostawcę LINQ IQueryable<T> interfejs do wykonywania zapytań magazynów danych relacyjnych.For example, the LINQ provider implements the IQueryable<T> interface for querying relational data stores. Kompilator języka C# kompiluje zapytań przeznaczonych dla tych źródeł danych do kodu, który kompiluje do drzewa wyrażenie w czasie wykonywania.The C# compiler compiles queries that target such data sources into code that builds an expression tree at runtime. Dostawca kwerend można przechodzić przez strukturę danych drzewa wyrażeń i tłumaczenie język zapytań, odpowiednie dla źródła danych.The query provider can then traverse the expression tree data structure and translate it into a query language appropriate for the data source.

Drzewa wyrażeń są również używane w składniku LINQ do reprezentowania wyrażeń lambda, które są przypisane do zmiennych typu Expression<TDelegate>.Expression trees are also used in LINQ to represent lambda expressions that are assigned to variables of type Expression<TDelegate>.

W tym temacie opisano, jak używać drzew wyrażeń do tworzenia dynamicznych zapytań LINQ.This topic describes how to use expression trees to create dynamic LINQ queries. Zapytania dynamiczne są przydatne, gdy szczegółowe informacje na temat zapytania nie są znane w czasie kompilacji.Dynamic queries are useful when the specifics of a query are not known at compile time. Na przykład aplikacja może dostarczyć interfejs użytkownika, który umożliwia użytkownikowi określić jeden lub więcej predykatów do filtrowania danych.For example, an application might provide a user interface that enables the end user to specify one or more predicates to filter the data. Aby można było używać programu LINQ do wykonywania zapytań, tego rodzaju aplikacji należy użyć drzew wyrażeń, aby utworzyć zapytanie LINQ w czasie wykonywania.In order to use LINQ for querying, this kind of application must use expression trees to create the LINQ query at runtime.

PrzykładExample

Poniższy przykład pokazuje jak używanie drzew wyrażeń do utworzenia zapytania dotyczącego IQueryable źródła danych, a następnie uruchomić go.The following example shows you how to use expression trees to construct a query against an IQueryable data source and then execute it. Kod zostanie skompilowany drzewa wyrażenie do reprezentowania następujące zapytanie:The code builds an expression tree to represent the following query:

companies.Where(company => (company.ToLower() == "coho winery" || company.Length > 16))
         .OrderBy(company => company)

Metodach fabryki w System.Linq.Expressions przestrzeni nazw są używane do tworzenia drzew wyrażeń, które reprezentują wyrażenia, które tworzą ogólną zapytania.The factory methods in the System.Linq.Expressions namespace are used to create expression trees that represent the expressions that make up the overall query. Wyrażenia, które reprezentują wywołania metody standardowego operatora zapytań odwoływać się do Queryable implementacji tych metod.The expressions that represent calls to the standard query operator methods refer to the Queryable implementations of these methods. Drzewa wyrażeń końcowego jest przekazywany do CreateQuery<TElement>(Expression) implementacji dostawcy IQueryable źródła danych do utworzenia pliku wykonywalnego zapytania typu IQueryable.The final expression tree is passed to the CreateQuery<TElement>(Expression) implementation of the provider of the IQueryable data source to create an executable query of type IQueryable. Wyniki są uzyskać, wyliczając tej zmiennej zapytania.The results are obtained by enumerating that query variable.

// Add a using directive for System.Linq.Expressions.  
  
string[] companies = { "Consolidated Messenger", "Alpine Ski House", "Southridge Video", "City Power & Light",  
                   "Coho Winery", "Wide World Importers", "Graphic Design Institute", "Adventure Works",  
                   "Humongous Insurance", "Woodgrove Bank", "Margie's Travel", "Northwind Traders",  
                   "Blue Yonder Airlines", "Trey Research", "The Phone Company",  
                   "Wingtip Toys", "Lucerne Publishing", "Fourth Coffee" };  
  
// The IQueryable data to query.  
IQueryable<String> queryableData = companies.AsQueryable<string>();  
  
// Compose the expression tree that represents the parameter to the predicate.  
ParameterExpression pe = Expression.Parameter(typeof(string), "company");  
  
// ***** Where(company => (company.ToLower() == "coho winery" || company.Length > 16)) *****  
// Create an expression tree that represents the expression 'company.ToLower() == "coho winery"'.  
Expression left = Expression.Call(pe, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));  
Expression right = Expression.Constant("coho winery");  
Expression e1 = Expression.Equal(left, right);  
  
// Create an expression tree that represents the expression 'company.Length > 16'.  
left = Expression.Property(pe, typeof(string).GetProperty("Length"));  
right = Expression.Constant(16, typeof(int));  
Expression e2 = Expression.GreaterThan(left, right);  
  
// Combine the expression trees to create an expression tree that represents the  
// expression '(company.ToLower() == "coho winery" || company.Length > 16)'.  
Expression predicateBody = Expression.OrElse(e1, e2);  
  
// Create an expression tree that represents the expression  
// 'queryableData.Where(company => (company.ToLower() == "coho winery" || company.Length > 16))'  
MethodCallExpression whereCallExpression = Expression.Call(  
    typeof(Queryable),  
    "Where",  
    new Type[] { queryableData.ElementType },  
    queryableData.Expression,  
    Expression.Lambda<Func<string, bool>>(predicateBody, new ParameterExpression[] { pe }));  
// ***** End Where *****  
  
// ***** OrderBy(company => company) *****  
// Create an expression tree that represents the expression  
// 'whereCallExpression.OrderBy(company => company)'  
MethodCallExpression orderByCallExpression = Expression.Call(  
    typeof(Queryable),  
    "OrderBy",  
    new Type[] { queryableData.ElementType, queryableData.ElementType },  
    whereCallExpression,  
    Expression.Lambda<Func<string, string>>(pe, new ParameterExpression[] { pe }));  
// ***** End OrderBy *****  
  
// Create an executable query from the expression tree.  
IQueryable<string> results = queryableData.Provider.CreateQuery<string>(orderByCallExpression);  
  
// Enumerate the results.  
foreach (string company in results)  
    Console.WriteLine(company);  
  
/*  This code produces the following output:  
  
    Blue Yonder Airlines  
    City Power & Light  
    Coho Winery  
    Consolidated Messenger  
    Graphic Design Institute  
    Humongous Insurance  
    Lucerne Publishing  
    Northwind Traders  
    The Phone Company  
    Wide World Importers  
*/  

Ten kod używa stałej liczby wyrażeń w predykacie, który jest przekazywany do Queryable.Where metody.This code uses a fixed number of expressions in the predicate that is passed to the Queryable.Where method. Jednakże można napisać aplikację, która łączy zmienną liczbę predykatu wyrażenia zależne od danych wejściowych użytkownika.However, you can write an application that combines a variable number of predicate expressions that depends on the user input. Mogą też występować różne standardowe operatory zapytań, które są wywoływane w zapytaniu, w zależności od danych wejściowych od użytkownika.You can also vary the standard query operators that are called in the query, depending on the input from the user.

Kompilowanie koduCompiling the Code

  • Obejmują System.Linq.Expressions przestrzeni nazw.Include the System.Linq.Expressions namespace.

Zobacz takżeSee also