怎使用表达式树生成动态查询。关于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地图