怎么着使用表达式树生成动态查询,关于Expression表明式树的拼接

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

在LINQ,表达式树常用于布局化查询,指标能源数量实现了
IQueryable.
比如,LINQ为关系型数据存款和储蓄查询提供了
IQueryable
接口。C#编写翻译器将这么些数据源的询问编写翻译成运维时的表明式树代码。然后查询提供程序能够遍历表明式树数据构造,并转账为适龄于数据源的询问语言。

在LINQ中动用表达式树来代表分配给
Expression
类型的拉姆da表明式变量。

那节首要描述了如何行使表明式树创设八个动态LINQ查询。在编译期,动态查询在极度未知的询问的图景下是丰裕实用的。具体育赛事例,叁个应用程序提供了七个顾客接口,最后来允许客户钦定二个或七个谓词来过滤数据。为了利用LINQ查询,这种情景应用程序在运作时必须选择表达式树来营造叁个LINQ查询。

关于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.拉姆da<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
方法中,在谓词中接纳了一个一定数字。然则,你能够写二个应用程序,来编写翻译在谓词中三个注重于顾客输入的数字变量。你也可以依据顾客的输入,更正查询中调用的规范查询操作符。

什么样利用表明式树生成动态查询

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

编写翻译代码

  • 开创新的调整台应用程序项目。
  • 丰裕对 System.Core.dll 的引用(若无引用)。
  • 席卷 System.Linq.Expressions 命名空间。
  • 从示例中复制代码,并将其粘贴到 Main 方法中。

[翻译]怎么样利用表达式树生成动态查询

在LINQ,表明式树常用于布局化查询,目的能源数量落成了 IQueryable.
举例,LINQ为关系型数据存款和储蓄查询提供了 IQueryable 接口。C#编写翻译器将这个数据源的询问编写翻译成运维时的表明式树代码。然后查询提供程序能够遍历表达式树数据结构,并转化为方便于数据源的查询语言。

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

那节主要描述了何等使用表达式树构建三个动态LINQ查询。在编写翻译期,动态查询在特殊未知的询问的气象下是非常低价的。具体育赛事例,三个应用程序提供了八个客商接口,最后来允许客户钦赐叁个或三个谓词来过滤数据。为了采用LINQ查询,这种情况应用程序在运转时必须利用表明式树来构建叁个LINQ查询。

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 方法中,在谓词中央银行使了贰个坚持住数字。可是,你能够写四个应用程序,来编译在谓词中叁个依靠于客户输入的数字变量。你也得以依照客商的输入,修改查询中调用的正规查询操作符。

编写翻译代码

  • 创制新的调整台应用程序大红鹰葡京会,项目。
  • 增进对 System.Core.dll 的引用(若无引用)。
  • 包含 System.Linq.Expressions 命名空间。
  • 从示例中复制代码,并将其粘贴到 Main 方法中。

但愿有个生活美好的次序人生

admin

网站地图xml地图