大红鹰葡京会安使用表达式树生成动态查询。关于Expression表达式树的拼接。

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

每当LINQ,表达式树常用于结构化查询,目标资源数量实现了
IQueryable.
例如,LINQ也涉项目数码存储查询提供了
IQueryable
接口。C#编译器将这些数据源的查询编译成运行时之表达式树代码。然后查询提供次可以遍历表达式树数据结构,并转账为当于数据源的询问语言。

以LINQ中采取表达式树来表示分配为
Expression
类型的Lambda表达式变量。

这节主要讲述了争使用表达式树构建一个动态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.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
方法被,在谓词中行使了一个稳数字。但是,你可以写一个应用程序,来编译在谓词中一个据让用户输入的数字变量。你为可因用户之输入,更改查询中调用的规范查询操作符。

怎么样用表达式树生成动态查询

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地图