EntityFramework动态多条件查询与Lambda表达式树
2017-12-08 22:21
351 查看
在常规的信息系统中,我们有需要动态多条件查询的情况,例如UI上有多个选择项可供用户选择多条件查询数据.
那么在.net平台EntityFramework下,我们用Lambda表达式树如何实现,这里我们需要一个PredicateBuilder的UML类图:
实现的代码是这样的:
[code]///Enablestheefficient,dynamiccompositionofquerypredicates.
[/code]
UnitTest的片断代码,一个产品查询的场景:
[code]BuildFindByAllQuery(productName,beignUpdateDate,endUpdateDate),
[/code]
UnitTest使用到生成查询条件的私有方法:
[code]///Buildsthefindbyallquery.
[/code]
上面的方法中由三个条件动态组成,一个是匹配productName,另两个是beginUpdateDate与endUpdateDate.在判断它们是否为时,构建最终查询条件集合.
最后把结果传给某个Repository类,完成相应的数据访问.
http://www.cnblogs.com/wintersun/p/3948227.html
那么在.net平台
实现的代码是这样的:
///<summary>
[code]///Enablestheefficient,dynamiccompositionofquerypredicates.
///</summary>
publicstaticclassPredicateBuilder
{
///<summary>
///Createsapredicatethatevaluatestotrue.
///</summary>
publicstaticExpression<Func<T,bool>>True<T>(){returnparam=>true;}
///<summary>
///Createsapredicatethatevaluatestofalse.
///</summary>
publicstaticExpression<Func<T,bool>>False<T>(){returnparam=>false;}
///<summary>
///Createsapredicateexpressionfromthespecifiedlambdaexpression.
///</summary>
publicstaticExpression<Func<T,bool>>Create<T>(Expression<Func<T,bool>>predicate){returnpredicate;}
///<summary>
///Combinesthefirstpredicatewiththesecondusingthelogical"and".
///</summary>
publicstaticExpression<Func<T,bool>>And<T>(thisExpression<Func<T,bool>>first,Expression<Func<T,bool>>second)
{
returnfirst.Compose(second,Expression.AndAlso);
}
///<summary>
///Combinesthefirstpredicatewiththesecondusingthelogical"or".
///</summary>
publicstaticExpression<Func<T,bool>>Or<T>(thisExpression<Func<T,bool>>first,Expression<Func<T,bool>>second)
{
returnfirst.Compose(second,Expression.OrElse);
}
///<summary>
///Negatesthepredicate.
///</summary>
publicstaticExpression<Func<T,bool>>Not<T>(thisExpression<Func<T,bool>>expression)
{
varnegated=Expression.Not(expression.Body);
returnExpression.Lambda<Func<T,bool>>(negated,expression.Parameters);
}
///<summary>
///Combinesthefirstexpressionwiththesecondusingthespecifiedmergefunction.
///</summary>
staticExpression<T>Compose<T>(thisExpression<T>first,Expression<T>second,Func<Expression,Expression,Expression>merge)
{
//zipparameters(mapfromparametersofsecondtoparametersoffirst)
varmap=first.Parameters
.Select((f,i)=>new{f,s=second.Parameters[i]})
.ToDictionary(p=>p.s,p=>p.f);
//replaceparametersinthesecondlambdaexpressionwiththeparametersinthefirst
varsecondBody=ParameterRebinder.ReplaceParameters(map,second.Body);
//createamergedlambdaexpressionwithparametersfromthefirstexpression
returnExpression.Lambda<T>(merge(first.Body,secondBody),first.Parameters);
}
///<summary>
///ParameterRebinder
///</summary>
classParameterRebinder:ExpressionVisitor
{
///<summary>
///TheParameterExpressionmap
///</summary>
readonlyDictionary<ParameterExpression,ParameterExpression>map;
///<summary>
///Initializesanewinstanceofthe<seecref="ParameterRebinder"/>class.
///</summary>
///<paramname="map">Themap.</param>
ParameterRebinder(Dictionary<ParameterExpression,ParameterExpression>map)
{
this.map=map??newDictionary<ParameterExpression,ParameterExpression>();
}
///<summary>
///Replacestheparameters.
///</summary>
///<paramname="map">Themap.</param>
///<paramname="exp">Theexp.</param>
///<returns>Expression</returns>
publicstaticExpressionReplaceParameters(Dictionary<ParameterExpression,ParameterExpression>map,Expressionexp)
{
returnnewParameterRebinder(map).Visit(exp);
}
///<summary>
///Visitstheparameter.
///</summary>
///<paramname="p">Thep.</param>
///<returns>Expression</returns>
protectedoverrideExpressionVisitParameter(ParameterExpressionp)
{
ParameterExpressionreplacement;
if(map.TryGetValue(p,outreplacement))
{
p=replacement;
}
returnbase.VisitParameter(p);
}
}
}
[/code]
UnitTest的片断代码,一个产品查询的场景:
varmyProduct=pr.Repository.Find(
[code]BuildFindByAllQuery(productName,beignUpdateDate,endUpdateDate),
e=>e.UpdatedTime,
pageIndex,
pageSize);
Assert.IsTrue(myProduct.Count>0);
[/code]
UnitTest使用到生成查询条件的私有方法:
///<summary>
[code]///Buildsthefindbyallquery.
///</summary>
privatestaticExpression<Func<Product,bool>>BuildFindByAllQuery(stringproductName,DateTime?beignUpdateDate,DateTime?endUpdateDate)
{
varlist=newList<Expression<Func<Product,bool>>>();
if(!string.IsNullOrEmpty(productName))list.Add(c=>c.ProductName==productName);
if(beignUpdateDate!=null)list.Add(c=>c.UpdatedTime>=beignUpdateDate);
if(endUpdateDate!=null)list.Add(c=>c.UpdatedTime<=endUpdateDate);
//Addmorecondition
Expression<Func<Product,bool>>productQueryTotal=null;
foreach(varexpressioninlist)
{
productQueryTotal=expression.And(expression);
}
returnproductQueryTotal;
}
[/code]
上面的方法中由三个条件动态组成,一个是匹配productName,另两个是beginUpdateDate与endUpdateDate.在判断它们是否为时,构建最终查询条件集合.
最后把结果传给某个Repository类,完成相应的数据访问.
相关文章推荐
- EntityFramework动态多条件查询与Lambda表达式树
- EntityFramework动态多条件查询与Lambda表达式树
- ibatis动态多条件查询及模糊查询(oracle,mysql,sql)
- Linq to SQL 多条件动态组合查询(实战篇)
- MySQL中动态生成多条件查询语句
- ajax多条件查询动态分页
- vb.net下根据查询条件动态改变水晶报表中的饼图效果
- ibatis动态查询条件
- Hibernate使用原生的动态sql实现带条件的查询分页功能
- 【Oracle】曾经的Oracle学习笔记(4-7)多表联合查询,子查询,动态条件查询
- JDBC的多条件动态查询
- Linq to Sql:N层应用中的查询(下) : 根据条件进行动态查询
- Spring data jpa 多表查询(三:多对多关系动态条件查询)
- linq to sql的多条件动态查询(上)
- linq to sql的多条件动态查询
- Jfinal适用于条件查询的动态SQL语句生成工具
- IBatisNet/IBatis动态条件查询XMl映射配置终极解决方案实例
- MongoDB动态条件之分页查询
- C# MongoDB 多条件动态组合查询
- asp.net 网页动态查询条件的实现