那么那个表明式体是一个怎么的项目呢,LINQ为关系型数据存储查询提供了

编译代码

  • 创设新的控制台应用程序项目。
  • 累加对 System.Core.dll 的引用(假若没有引用)。
  • 席卷 System.Linq.Expressions 命名空间。
  • 从示例中复制代码,并将其粘贴到 Main 方法中。

关于Expression表达式树的拼接

 

不久前在做项目中遭逢一个问题,需求是这样的:

本人要对已经存在的用户进行搜索,可以按照用户的id
或者用户名其中的一局部字符来查找出来,这样就出现了三种情况只有id,只有用户名中一部字符,或者全部都有.

咱俩用的MVC+EF5.0的框架,在BLL层举办询问的
时候需要构建lambda表明式来作为查询条件,不过,大家怎么来构建lambda来确定询问的条件吧?我们知道Express<Func<T,bool>>这样的一个参数可以是lambda表明式,不过这里的按规范拼接式无法运用委托链的样式的.当然还有一种解决办法,我把持有查询条件都写好,然后依照传过来的ID
或者用户名
来判断确定使用哪个..这样的论断逻辑混乱,代码冗长,我们就想找一个可以动态拼接查询条件的方法.

即遵照id 或者用户名是否存在动态的来拼接查询条件.

第一我们需要知道,表明式构成部分,表明式是有两有些构成,Parameter和body,第一个是参数,第二个是发挥式体,说明式体是二进制的位运算,也就是
比如(left&right)而left和right要重临的值必须是核心类型的值,也就是足以涉足位运算的值.例如(a,b)=>()这么些lambda表达式中,ab是参数,括号前面中是表述式体这其中再次来到的值只可以是基本类型.我们要构建一个表明式树,重要就是构建这么些表明式体,那么这个表明式体是一个怎么的类型呢
?BinaryExpression类型,我们只需要结构这个项目,然后通过Expression.And(left,right)或者Expression.Or()这多少个措施来协会即可.
这几个五个艺术重回值就是BinaryExpression的花色对象.然后我们在用Expression.Lambda<Func<T,bool>>(BinaryExpression,Parameter)那么些法子将那些表明式树转化为lambda的表述式.这就是以此问题的
解决思路,来探望我们是怎么来贯彻的.

首先大家定义了一个表达式变量.

Expression<Func<UserInfo, bool>> where;

下一场我们最先举行labmda的布局

接下去,大家来社团参数和必要条件,也是就lambda中的c=>()中的c

图片 1

ParameterExpression param = Expression.Parameter(typeof(UserInfo), "c");//c=>

            //c=>c.IsDelete==false这里需要不被删除的条件

            MemberExpression left1 = Expression.Property(param, typeof(UserInfo).GetProperty("IsDelete"));构建c.IsDelete

            ConstantExpression right1 = Expression.Constant(false);//构建一个常量 false

            BinaryExpression be = Expression.Equal(left1, right1);构建//c=>c.IsDelete==false 就是现在这个be了

图片 2

 

下边 大家需要按照我们的尺度 也就是id和用户名字符串来连续拼接那多少个表达式

率先我们来拼接c.UserId==sid

图片 3

if (!string.IsNullOrEmpty(Request["sid"]))

            {

                //c.UserId==sid

                int sid = int.Parse(Request["sid"]);

                //根据参数的属性构造左表达式c.UserId

                MemberExpression left2 = Expression.Property(param, typeof(UserInfo).GetProperty("UserId"));

                //构造右表达式sid

                ConstantExpression right2 = Expression.Constant(sid);

                //进行合并:cUserId==sid

                BinaryExpression where2 = Expression.Equal(left2, right2);

                //将这个条件与上一个条件进行与合并:c.IsDelete==false && c.UserId==sid

                be = Expression.And(be, where2);

            }

图片 4

 

现今我们来拼接第二个规范

前方大家曾经说过,表达式体需要重临的是足以做二进制运算的档次,不过这是个值类型字符串,该如何是好吧?

在参考了MSDN中的Expression方法中,发现有这般的一个方法.Expression.Call().

然后看了示例这个

 

究竟是用来干嘛的??

咱俩得以用这多少个call’方法 ,来调用一个门类
中的一个措施,然后爆发一个MethodCallExpression类型的重临值,这样,我们来调用string.
Contains方法不就可以做到我们想要的表明式了么?

且看下边的 代码

图片 5

//c.UserName.Contains(sname)

            if (!string.IsNullOrEmpty(Request["sname"]))

            {

                string sname = Request["sname"];

                MemberExpression left3 = Expression.Property(param, typeof(UserInfo).GetProperty("UserName"));//这里构造c.UserName这个属性表达式.

                ConstantExpression right3 = Expression.Constant(sname);//这里构造sname这个常量表达式

                MethodCallExpression where3 = Expression.Call(left3, typeof(string).GetMethod("Contains"), right3);这里我们用Call这个方法完成/c.UserName.Contains(sname)这个lambda这个表达式的实现.

                be = Expression.And(be, where3);//拼接刚才的be表达式,

            }

where = Expression.Lambda<Func<UserInfo, bool>>(be, param);//生成最后需要的带参数的表达式树.

图片 6

 

如此我们的表明式树拼接就成功了.

至于运行结果就不为大家贴图了,可以运行和lambda的结果一样.方可做到七个标准化的查询.

上面,封装了这多少个表明式树的帮助类.我们可以参考.

图片 7

public class WhereHelper<T>

        where T:class

    {

        private ParameterExpression param;

        private BinaryExpression filter;

        public WhereHelper()

        {

            param = Expression.Parameter(typeof (T), "c");

            //1==1

            Expression left = Expression.Constant(1);

            filter = Expression.Equal(left, left);

        }

        public Expression<Func<T, bool>> GetExpression()

        {

            return Expression.Lambda<Func<T, bool>>(filter,param);

        }

        public void Equal(string propertyName,object value)

        {

            Expression left = Expression.Property(param, typeof (T).GetProperty(propertyName));

            Expression right = Expression.Constant(value, value.GetType());

            Expression result = Expression.Equal(left, right);

            filter = Expression.And(filter, result);

        }

        public void Contains(string propertyName,string value)

        {

            Expression left = Expression.Property(param, typeof (T).GetProperty(propertyName));

            Expression right = Expression.Constant(value, value.GetType());

            Expression result = Expression.Call(left, typeof (string).GetMethod("Contains"), right);

            filter = Expression.And(filter, result);

        }

}

图片 8

 

自然,这些帮助类效用有限,假如有需要者,我们可以团结开展增添.

正文所提到的技能,均为我师研商,因为她探究完之后就给大家讲解了规律和实现.我只是整理出来,给我们做

原文  http://www.cnblogs.com/ruhuaxiao/p/3773596.html

 

 

 

 

Example

下边这段代码显示怎么样使用表明式树去围绕 IQueryable
数据源构造一个查询并运行。代码生成了一个表明式树来代表查询:

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

在命名空间
[System.Linq.Expressions](https://docs.microsoft.com/en-us/dotnet/api/system.linq.expressions)
下有个工厂方法用来生成一个表明式树来代表那么些查询。表示专业查询运算符方法调用的表明式将引用这一个点子的
Queryable
的落实。最后表明式树被传送给 IQueryable 数据源的提供程序的
CreateQuery(Expression)
实现,以创立一个可实施的 IQueryable
类型的询问。通过枚举该查询得到结果。

Expression<Func<string, bool>> expr = name => name.Length > 10 && name.StartsWith("G");
Console.WriteLine(expr);

AndAlsoModifier treeModifier = new AndAlsoModifier();
Expression modifierExpr = treeModifier.Modify(expr);

Console.WriteLine(modifierExpr);

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();
//编写表示谓词参数的表达式树
ParameterExpression pe = Expression.Parameter(typeof(string), "company");
//新建一个表达式树来表示 'company.ToLower() == "coho winery"' 的表达式
Expression left = Expression.Call(pe, typeof(string).GetMethod("ToLower", Type.EmptyTypes));
Expression right = Expression.Constant("coho winery", typeof(string));
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 whereCallExpresstion = Expression.Call(
    typeof(Queryable),
    "Where",
    new Type[] { queryableData.ElementType },
    queryableData.Expression,
    Expression.Lambda<Func<string, bool>>(predicateBody, new ParameterExpression[] { pe }));

//排序 OrderBy(company => company)
//新建一个表达式树来表示 'whereCallExpression.OrderBy(company => company)'
MethodCallExpression orderCallExpresstion = Expression.Call(
    typeof(Queryable),
    "OrderBy",
    new Type[] { queryableData.ElementType, queryableData.ElementType },
    whereCallExpresstion,
    Expression.Lambda<Func<string, string>>(pe, new ParameterExpression[] { pe }));

//新建一个可执行的查询表达式树
IQueryable<string> result = queryableData.Provider.CreateQuery<string>(orderCallExpresstion);

//枚举结果
foreach (string company in companies)
    Console.WriteLine(company);

代码中在被传送到 Queryable.Where
方法中,在谓词中采纳了一个原则性数字。然则,你能够写一个应用程序,来编译在谓词中一个倚重于用户输入的数字变量。你也足以遵照用户的输入,更改查询中调用的标准查询操作符。

[翻译]何以使用表明式树生成动态查询

在LINQ,表达式树常用于结构化查询,指标资源数量实现了 IQueryable.
例如,LINQ为关系型数据存储查询提供了 IQueryable 接口。C#编译器将这些数据源的查询编译成运行时的表达式树代码。然后查询提供程序可以遍历表达式树数据结构,并转账为适龄于数据源的询问语言。

在LINQ中选取表达式树来表示分配给 Expression 类型的兰姆da表明式变量。

那节首要讲述了怎么利用表明式树构建一个动态LINQ查询。在编译期,动态查询在非常规未知的查询的动静下是可怜实用的。具体事例,一个应用程序提供了一个用户接口,最后来允许用户指定一个或两个谓词来过滤数据。为了利用LINQ查询,这种情形应用程序在运转时务必运用表明式树来构建一个LINQ查询。

[翻译]如何使用表达式树生成动态查询

在LINQ,表明式树常用于结构化查询,目的资源数量实现了
IQueryable.
例如,LINQ为关系型数据存储查询提供了
IQueryable
接口。C#编译器将这么些数据源的询问编译成运行时的表明式树代码。然后查询提供程序可以遍历表达式树数据结构,并转账为适龄于数据源的询问语言。

在LINQ中应用表明式树来表示分配给
Expression
类型的Lambda表明式变量。

这节重要讲述了什么利用表达式树构建一个动态LINQ查询。在编译期,动态查询在很是未知的查询的景色下是可怜有效的。具体事例,一个应用程序提供了一个用户接口,最后来允许用户指定一个或两个谓词来过滤数据。为了采取LINQ查询,这种景色应用程序在运行时必须接纳表明式树来构建一个LINQ查询。

编译代码

  • 开立异的控制台应用程序项目。
  • 增长对 System.Core.dll 的引用(虽然没有引用)。
  • 包括 System.Linq.Expressions 命名空间。
  • 从示例中复制代码,并将其粘贴到 Main 方法中。

盼望有个生活美好的主次人生

Example

下边这段代码显示怎么着接纳表明式树去围绕 IQueryable 数据源构造一个询问并运行。代码生成了一个表明式树来代表查询:

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

在命名空间 [System.Linq.Expressions](https://docs.microsoft.com/en-us/dotnet/api/system.linq.expressions) 下有个工厂方法用来生成一个表明式树来代表这么些查询。表示专业查询运算符方法调用的表达式将引用这个办法的 Queryable 的落实。最终表明式树被传送给 IQueryable 数据源的提供程序的 CreateQuery(Expression) 实现,以创建一个可实施的 IQueryable 类型的询问。通过枚举该查询得到结果。

Expression<Func<string, bool>> expr = name => name.Length > 10 && name.StartsWith("G");
Console.WriteLine(expr);

AndAlsoModifier treeModifier = new AndAlsoModifier();
Expression modifierExpr = treeModifier.Modify(expr);

Console.WriteLine(modifierExpr);

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();
//编写表示谓词参数的表达式树
ParameterExpression pe = Expression.Parameter(typeof(string), "company");
//新建一个表达式树来表示 'company.ToLower() == "coho winery"' 的表达式
Expression left = Expression.Call(pe, typeof(string).GetMethod("ToLower", Type.EmptyTypes));
Expression right = Expression.Constant("coho winery", typeof(string));
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 whereCallExpresstion = Expression.Call(
    typeof(Queryable),
    "Where",
    new Type[] { queryableData.ElementType },
    queryableData.Expression,
    Expression.Lambda<Func<string, bool>>(predicateBody, new ParameterExpression[] { pe }));

//排序 OrderBy(company => company)
//新建一个表达式树来表示 'whereCallExpression.OrderBy(company => company)'
MethodCallExpression orderCallExpresstion = Expression.Call(
    typeof(Queryable),
    "OrderBy",
    new Type[] { queryableData.ElementType, queryableData.ElementType },
    whereCallExpresstion,
    Expression.Lambda<Func<string, string>>(pe, new ParameterExpression[] { pe }));

//新建一个可执行的查询表达式树
IQueryable<string> result = queryableData.Provider.CreateQuery<string>(orderCallExpresstion);

//枚举结果
foreach (string company in companies)
    Console.WriteLine(company);

代码中在被传送到 Queryable.Where 方法中,在谓词中采用了一个恒定数字。然而,你可以写一个应用程序,来编译在谓词中一个依赖于用户输入的数字变量。你也得以遵照用户的输入,更改查询中调用的正规查询操作符。

哪些使用表明式树生成动态查询

2018-01-11 12:11 by 沉睡的木木夕, 33 阅读, 0 评论, 收藏编辑

相关文章