表达式树(四)【如何使用表达式树来生成动态查询 (C#)】

在 LINQ 中,表达式树用于表示针对数据源的结构化查询,这些数据源可实现System.Linq.IQueryable。 例如,LINQ 提供程序可实现 System.Linq.IQueryable接口,用于查询关系数据存储。 C# 编译器将针对此类数据源的查询编译为代码,该代码在运行时会生成一个表达式树。 然后,查询提供程序可以遍历表达式树数据结构,并将其转换为适合于数据源的查询语言。

表达式树还可以用在 LINQ 中,用于表示分配给类型为 System.Linq.Expressions.Expression 的变量的 lambda 表达式。

本主题描述如何使用表达式树来创建动态 LINQ 查询。 如果在编译时不知道查询的细节,动态查询将十分有用。 例如,应用程序可能会提供一个用户界面,最终用户可以使用该用户界面指定一个或多个谓词来筛选数据。 为了使用 LINQ 进行查询,这种应用程序必须使用表达式树在运行时创建 LINQ 查询。

示例

下面的示例演示如何使用表达式树依据 IQueryable 数据源构造一个查询,然后执行该查询。 代码将生成一个表达式树来表示以下查询:

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

System.Linq.Expressions 命名空间中的工厂方法用于创建表达式树,这些表达式树表示构成总体查询的表达式。 表示标准查询运算符方法调用的表达式将引用这些方法的 System.Linq.Queryable实现。 最终的表达式树将传递给 IQueryable 数据源的提供程序的 System.Linq.IQueryProvider.CreateQuery System.Linq.Expressions.Expression 实现,以创建 IQueryable 类型的可执行查询。 通过枚举该查询变量获得结果。

// 为 System.Linq.Expressions 添加 using 指令
  
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" };  
  
//要查询的 IQueryable 数据
IQueryable<String> queryableData = companies.AsQueryable<string>();  
  

//组成表示谓词参数的表达式树
ParameterExpression pe = Expression.Parameter(typeof(string), "company");  
  
// ***** Where(company => (company.ToLower() == "coho winery" || company.Length > 16)) *****  
//创建一个表示表达式 '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);  
  

// 创建一个表示表达式'company.Length > 16'的表达式树。
left = Expression.Property(pe, typeof(string).GetProperty("Length"));  
right = Expression.Constant(16, typeof(int));  
Expression e2 = Expression.GreaterThan(left, right);  
  
//组合表达式树以创建表示表达式'(company.ToLower() == "coho winery" || company.Length > 16)'的表达式树。
Expression predicateBody = Expression.OrElse(e1, e2);  


//创建表示表达式的表达式树'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) *****  

//创建表示表达式'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 *****  


//从表达式树创建一个可执行查询。
IQueryable<string> results = queryableData.Provider.CreateQuery<string>(orderByCallExpression);  
  
// 列举结果
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  
*/  

此代码在传递到 Queryable.Where 方法的谓词中使用固定数量的表达式。 但是,可以编写一个视用户输入而定来合并可变数量谓词表达式的应用程序。 视用户输入而定,也可以更改在查询中调用的标准查询运算符。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值