Udostępnij za pośrednictwem


Jak: tworzenie kwerend dynamicznych (C# i Visual Basic) przy użyciu wyrażenia drzewa

W LINQ, drzewach wyrażeń są używane do przedstawiania strukturę zapytań, które współpracować z źródeł danych, który implementuje IQueryable<T>.Na przykład LINQ to SQL Implementacja dostawcy IQueryable<T> interfejsu dla kwerendy relacyjnej bazie danych przechowuje.C# i Visual Basic kompilatory kompilowania kwerend, które współpracować z takich źródeł danych na kod, który opiera się w drzewie wyrażenie w czasie wykonywania.Dostawca kwerendy można przechodzić przez wyrażenie tree struktury danych i przetłumaczyć na język kwerendy właściwe dla źródła danych.

Drzewach wyrażeń są także używane w LINQ do reprezentowania wyrażenia lambda, które są przypisane do zmiennych typu Expression<TDelegate>.

W tym temacie opisano sposób używania drzewach wyrażeń do tworzenia dynamicznych LINQ kwerend.Dynamiczne kwerendy są przydatne, gdy charakterystyka kwerendy nie są znane w czasie kompilacji.Na przykład aplikacja może być dostarcza interfejs użytkownika, który umożliwia użytkownikowi końcowemu określić jeden lub więcej predykatów do filtrowania danych.Aby korzystać z LINQ do wykonywania kwerend, tego typu aplikacji należy użyć drzewach wyrażeń do utworzenia LINQ kwerendy w czasie wykonywania.

Przykład

Poniższy przykład pokazuje sposób używania drzewach wyrażeń do skonstruowania kwerendy przeciwko IQueryable źródło danych, a następnie uruchamiamy.Kod buduje drzewo wyrażenie do reprezentowania następującej kwerendy:

Kwerendy języka C#

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

Kwerendy języka Visual Basic

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

Metody fabryki w System.Linq.Expressions obszaru nazw są używane do tworzenia drzewach wyrażeń, które reprezentują wyrażeń, które tworzą ogólny kwerendy.Wyrażenia, które reprezentują wywołania metod operator standardowej kwerendy odwoływać się do Queryable implementacji tych metod.Drzewo ostatniego wyrażenia są przekazywane do CreateQuery<TElement>(Expression) realizacji z dostawcą IQueryable źródło danych, aby utworzyć kwerendę wykonywalny typu IQueryable.Wyniki są otrzymywane przez wyliczanie tej zmiennej kwerendy.

        ' Add an Imports statement for System.Linq.Expressions.

        Dim 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.
        Dim queryableData As IQueryable(Of String) = companies.AsQueryable()

        ' Compose the expression tree that represents the parameter to the predicate.
        Dim pe As ParameterExpression = Expression.Parameter(GetType(String), "company")

        ' ***** Where(Function(company) company.ToLower() = "coho winery" OrElse company.Length > 16) *****
        ' Create an expression tree that represents the expression: company.ToLower() = "coho winery".
        Dim left As Expression = Expression.Call(pe, GetType(String).GetMethod("ToLower", System.Type.EmptyTypes))
        Dim right As Expression = Expression.Constant("coho winery")
        Dim e1 As Expression = Expression.Equal(left, right)

        ' Create an expression tree that represents the expression: company.Length > 16.
        left = Expression.Property(pe, GetType(String).GetProperty("Length"))
        right = Expression.Constant(16, GetType(Integer))
        Dim e2 As Expression = Expression.GreaterThan(left, right)

        ' Combine the expressions to create an expression tree that represents the
        ' expression: company.ToLower() = "coho winery" OrElse company.Length > 16).
        Dim predicateBody As Expression = Expression.OrElse(e1, e2)

        ' Create an expression tree that represents the expression:
        ' queryableData.Where(Function(company) company.ToLower() = "coho winery" OrElse company.Length > 16)
        Dim whereCallExpression As MethodCallExpression = Expression.Call( 
                GetType(Queryable), 
                "Where", 
                New Type() {queryableData.ElementType}, 
                queryableData.Expression, 
                Expression.Lambda(Of Func(Of String, Boolean))(predicateBody, New ParameterExpression() {pe}))
        ' ***** End Where *****

        ' ***** OrderBy(Function(company) company) *****
        ' Create an expression tree that represents the expression:
        ' whereCallExpression.OrderBy(Function(company) company)
        Dim orderByCallExpression As MethodCallExpression = Expression.Call( 
                GetType(Queryable), 
                "OrderBy", 
                New Type() {queryableData.ElementType, queryableData.ElementType}, 
                whereCallExpression, 
                Expression.Lambda(Of Func(Of String, String))(pe, New ParameterExpression() {pe}))
        ' ***** End OrderBy *****

        ' Create an executable query from the expression tree.
        Dim results As IQueryable(Of String) = queryableData.Provider.CreateQuery(Of String)(orderByCallExpression)

        ' Enumerate the results.
        For Each company As String In results
            Console.WriteLine(company)
        Next

        ' 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

            // 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 zawiera stałą liczbę wyrażeń w predykacie, który jest przekazywany do Queryable.Where metoda.Jednakże można napisać aplikację, która łączy zmienna liczba predykatu wyrażenia, która zależy od danych wejściowych użytkownika.Istnieje też możliwość zróżnicowania operatory standardowej kwerendy, które są wywoływane w kwerendzie, w zależności od danych wejściowych od użytkownika.

Kompilowanie kodu

  • Utwórz nowy Console Application projektu w Visual Studio.

  • Dodaj odwołanie do System.Core.dll, jeśli nie jest wywoływany.

  • Dołącz obszar nazw System.Linq.Expressions.

  • Skopiuj kod z przykładu i wklej go do Main metoda (C#) lub MainSub procedura (Visual Basic).

Zobacz też

Zadania

Jak: wykonywanie wyrażenie drzew (C# i Visual Basic)

Jak: dynamicznie określ filtry predykat w czasie wykonywania (Podręcznik programowania C#)

Koncepcje

Wyrażenie drzew (C# i Visual Basic)

Inne zasoby

Materiał siewny farmy LINQ: Za pomocą podglądacza drzewa wyrażenie