LINQ to SQL语句(23)之动态查询

动态查询

有这样一个场景:应用程序可能会提供一个用户界面,用 户可以使用该用户界面指定一个或多个谓词来筛选数据。这种情况在编译时不知 道查询的细节,动态查询将十分有用。

在LINQ中,Lambda表达式是许多 标准查询运算符的基础,编译器创建lambda表达式以捕获基础查询方法(例如 Where、Select、Order By、Take While 以及其他方法)中定义的计算。表达式 目录树用于针对数据源的结构化查询,这些数据源实现IQueryable<T>。 例如,LINQ to SQL 提供程序实现 IQueryable<T>接口,用于查询关系数 据存储。C#和Visual Basic编译器会针对此类数据源的查询编译为代码,该代码 在运行时将生成一个表达式目录树。然后,查询提供程序可以遍历表达式目录树 数据结构,并将其转换为适合于数据源的查询语言。

表达式目录树在 LINQ中用于表示分配给类型为Expression<TDelegate>的变量的Lambda表 达式。还可用于创建动态LINQ查询。

System.Linq.Expressions命名空间 提供用于手动生成表达式目录树的API。Expression类包含创建特定类型的表达 式目录树节点的静态工厂方法,例如,ParameterExpression(表示一个已命名 的参数表达式)或 MethodCallExpression(表示一个方法调用)。编译器生成 的表达式目录树的根始终在类型Expression<TDelegate>的节点中,其中 TDelegate是包含至多五个输入参数的任何TDelegate委托;也就是说,其根节点 是表示一个lambda表达式。

下面几个例子描述如何使用表达式目录树来 创建动态LINQ查询。

1.Select

下面例子说明如何使用表达式树 依据 IQueryable 数据源构造一个动态查询,查询出每个顾客的ContactName, 并用GetCommand方法获取其生成SQL语句。

//依据IQueryable数据 源构造一个查询
IQueryable<Customer> custs = db.Customers;
//组建一个表达式树来创建一个参数
ParameterExpression param =
  Expression.Parameter(typeof (Customer), "c");
//组建表达式树:c.ContactName
Expression selector = Expression.Property(param,
  typeof (Customer).GetProperty("ContactName"));
Expression pred = Expression.Lambda(selector, param);
//组建表达式树:Select (c=>c.ContactName)
Expression expr = Expression.Call(typeof (Queryable), "Select",
  new Type[] { typeof (Customer), typeof(string) },
  Expression.Constant(custs), pred);
//使用表达式树来生成动态查询
IQueryable<string> query = db.Customers.AsQueryable()
   .Provider.CreateQuery<string>(expr);
//使用GetCommand方法 获取SQL语句
System.Data.Common.DbCommand cmd = db.GetCommand (query);
Console.WriteLine(cmd.CommandText);

生成的 SQL语句为:

SELECT [t0].[ContactName] FROM [dbo]. [Customers] AS [t0]2.Where

下面一个例子是“搭建 ”Where用法来动态查询城市在伦敦的顾客。

IQueryable<Customer> custs = db.Customers;
// 创建一个参数c
ParameterExpression param =
   Expression.Parameter(typeof(Customer), "c");
//c.City=="London"
Expression left = Expression.Property(param,
  typeof(Customer).GetProperty ("City"));
Expression right = Expression.Constant ("London");
Expression filter = Expression.Equal(left, right);
Expression pred = Expression.Lambda(filter, param);
//Where(c=>c.City=="London")
Expression expr = Expression.Call(typeof(Queryable), "Where",
  new Type[] { typeof(Customer) },
  Expression.Constant(custs), pred);
//生成动态查询
IQueryable<Customer> query = db.Customers.AsQueryable()
   .Provider.CreateQuery<Customer>(expr);

生成的SQL 语句为:

SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName],
[t0].[ContactTitle], [t0].[Address], [t0]. [City], [t0].[Region],
[t0].[PostalCode], [t0].[Country], [t0]. [Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0] WHERE [t0]. [City] = @p0
-- @p0: Input NVarChar (Size = 6; Prec = 0; Scale = 0) [London]

时间: 2025-01-02 20:00:42

LINQ to SQL语句(23)之动态查询的相关文章

linq to sql的多条件动态查询(上)

linq  to sql的多条件动态查询确实是一件头痛的事情,用表达式树或反射方法要写一大堆代码,有时候想想与其这么复杂,还不如回到手动sql拼接的年代,但是技术总是向前发展的,终归还是要在linq上解决这一问题,无意在网上发现一个还算比较简单的办法,分享一下: void ShowData()     {        using (DBDataContext db = new DBDataContext(Database.ConnectionString))        {         

用非动态SQL Server SQL语句来对动态查询进行执行

此文章主要向大家讲述的是非动态SQL ServerSQL语句执行动态查询,在实际操作中我尝试在一个存储过程中,来进行传递一系列以逗号划定界限的值,来对结果集进行限制.但是无论什么时候,我在IN子句中使用变量,都会得到错误信息. 是否存在一种不执行动态SQL语句也能完成查询的方式呢? 我尝试在一个存储过程中传递一系列以逗号划定界限的值,以限制结果集.但是无论什么时候,我在IN子句中使用变量,都会得到错误信息.是否存在一种不执行动态SQL ServerSQL语句也能完成查询的方式呢? 专家解答: 这

linq to sql的多条件动态查询(下)

借助老外写的一个扩展表达式的类,可以把上篇中的代码写得更优雅 这是PredicateBuilder的源文件  public static class PredicateBuilder    ...{      public static Expression<Func<T, bool>> True<T> ()  ...{ return f => true;  }      public static Expression<Func<T, bool>

通过非动态SQL语句在SQL Server中执行动态查询

问题: 我尝试在一个存储过程中传递一系列以逗号划定界限的值,以限制结果集.但是无论什么时候,我在 IN子句中使用变量,都会得到错误信息.是否存在一种不执行动态SQL语句也能完成查询的方式呢? 专家解答: 这里存在一种不执行动态SQL语句也能完成查询的方式,但是首先让我们来探究这个问题.我将在以下 例子中运用AdventureWorks数据库. 在你只有一个值的时候,执行将不会有什么问题. Declare @ManagerIDs Varchar(100) Set @ManagerIDs = '3'

LINQ体验(8)—LINQ to SQL语句之Union All/Union/Intersect和Top/Bottom和Pag

LINQ体验(8)-LINQ to SQL语句之Union All/Union/Intersect和Top/Bottom和Paging和SqlMethods 我们继续讲解LINQ to SQL语句,这篇我们来讨论Union All/Union/Intersect操作和Top/Bottom操作和Paging操作和SqlMethods操作 . Union All/Union/Intersect操作 适用场景:对两个集合的处理,例如追加.合并.取相同项.相交项等等. Concat(连接) 说明:连接不

LINQ体验(5)——LINQ to SQL语句之Select/Distinct和Count/Sum/Min/Max/Avg

上一篇讲述了LINQ,顺便说了一下Where操作,这篇开始我们继续说LINQ to SQL语句,目的让大家从语句的角度了解LINQ,LINQ包括LINQ to Objects.LINQ to DataSets.LINQ to SQL.LINQ to Entities.LINQ to XML,但是相对来说LINQ to SQL在我们程序中使用最多,毕竟所 有的数据都要在数据库运行着各种操作.所以先来学习LINQ to SQL,其它的都差不多了,那么就从Select说起吧,这个在编写程序中也最为常

LINQ体验(9)——LINQ to SQL语句之Insert/Update/Delete操作

我们继续讲解LINQ to SQL语句,这篇我们来讨论Insert/Update/Delete操作 .这个在我们的程序中最为常用了.我们直接看例子. Insert/Update/Delete操作插入(Insert)1.简单形式 说明:new一个 对象,使用InsertOnSubmit方法将其加入到对应的集合中,使用SubmitChanges ()提交到数据库. NorthwindDataContext db = new NorthwindDataContext(); var newCustome

LINQ体验(7)-LINQ to SQL语句之Group By/Having和Exists/In/Any/All/Contains

我们继续讲解LINQ to SQL语句,这篇我们来讨论Group By/Having操作符和 Exists/In/Any/All/Contains操作符. Group By/Having操作符 适用 场景:分组数据,为我们查找数据缩小范围. 说明:分配并返回对传入 参数进行分组操作后的可枚举对象.分组:延迟 1.简单形式: var q = from p in db.Products group p by p.CategoryID into g select g; 语句描述:使用Group By

SQL语句实现子孙树查询经典实例

 下面介绍的SQL语句非常经典,该SQL语句实现子孙树查询,该SQL语句可以直接在查询分析器中执行,供您参考. --生成表   create table MENU(id int,mname char(50),parent int)     --插入数据   insert into MENU    select 1,'新闻',Null union all   select 2,'房产',Null union all   select 3,'科技新闻',1 union all   select 4,