Sdílet prostřednictvím


Postupy: Použití stromů výrazů k sestavování dynamických dotazů (C# a Visual Basic)

V LINQ, stromy výrazů se používají k reprezentaci strukturované dotazy, které se zaměřují na zdroji dat, které implementují IQueryable.Například Technologie LINQ to SQL implementuje zprostředkovatele IQueryable rozhraní pro dotazování na relační datové úložiště.C# a Visual Basic kompilátory kompilací dotazů, které se zaměřují na tyto zdroje dat do kódu, který vytvoří strom výrazů za běhu.Dotaz zprostředkovatele můžete procházet stromové struktury dat. výraz a překládat do dotazovací jazyk, který je vhodný pro zdroj dat.

Stromy výrazů jsou také používá LINQ představuje lambda výrazy, které jsou přiřazeny proměnným typu Expression.

Toto téma popisuje způsob použití dojte k vytvoření dynamických LINQ dotazy.Dynamické dotazy jsou vhodné při specifika dotazu nejsou známy v době kompilace.Aplikace může například poskytnout uživatelské rozhraní, které umožňuje koncovému uživateli zadat jeden nebo více predikátů filtrovat data.Chcete-li použít LINQ pro dotazování, musí tento druh aplikace použít dojte k vytvoření LINQ dotazu za běhu.

Příklad

Následující příklad ukazuje, jak použít k vytvoření dotazu proti dojte IQueryable zdroje dat a potom spustit.Kód vytvoří strom výrazů představovat následující dotaz:

Dotaz v jazyce C#

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

Dotaz v jazyce Visual Basic

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

Metody výroby v System.Linq.Expressions oboru názvů slouží k vytvoření stromy výrazů, které představují výrazy, které tvoří celkové dotazu.Výrazy, které představují volání metody standardních dotazovacích operátorů naleznete Queryable implementace těchto metod.Strom výsledný výraz je předána CreateQuery``1(Expression) implementace poskytovatele IQueryable zdroje dat k vytvoření spustitelného dotazu typu IQueryable.Výsledky jsou získány výčtem dané proměnné dotazu.

        ' 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
            */

Tento kód používá pevný počet výrazů v predikátu, která je předána Queryable.Where metoda.Nicméně můžete napsat aplikaci, která kombinuje proměnný počet predikátu výrazy, které závisí na uživatelský vstup.Můžete také měnit standardních dotazových operátorů, které jsou volány v aplikaci query, v závislosti na vstup od uživatele.

Probíhá kompilace kódu

  • Vytvořte novou Aplikace konzoly projektu v Visual Studio.

  • Pokud již není odkazováno, přidejte odkaz na System.Core.dll.

  • Obor názvů System.Linq.Expressions obsahují.

  • Kód z příkladu zkopírujte a vložte jej do Main metody (C#) nebo MainSub postupu (Visual Basic).

Viz také

Úkoly

Postupy: Provádění stromů výrazů (C# a Visual Basic)

Postupy: Dynamické určování filtrů predikátů při běhu (Průvodce programováním v C#)

Koncepty

Stromy výrazů (C# a Visual Basic)

Další zdroje

LINQ farmy osiva: Použití Visualizer stromu výraz