最近这几天做的东西总算是回归咱的老本行了,给投资管理项目做一个台账的东西,就是类似我们的报表。其
中有一个功能是一个高级查询的需求,在查询条件方面大概有7、8个查询条件。需求就是如果一个条件都不输入就默
认查询全部的数据,那个条件不为空的时候就在查询条件上面添加对响应字段的限制,也就是说我们在写查询条件的
时候不能写死,因为我们不知道我们到底有几个条件?到底有几个条件。所以需要我们动态的创建Lambd表达式。看
了看他们相似的功能,在实现的时候用的动态拼接SQL语句,那些SQL代码啊?看到都头疼,所以我直接放弃了,用咱
自己熟悉的知识来实现。和这个相似的功能自己在之前的《图书馆项目》中实现过,请点击我。
首先需要引入命名空间
using System.Linq.Expressions.Expression;
//创建一个数组用来当做例子
var ints = new int []{ 1, 2 , 3 , 4 , 5 , 6 };
// 要创建形如 i => i < 5
//创建参数 i
var parameter = Expression.Parameter(typeof(int),”i”);
//创建常数 5
var constant = Expression.Constant(5);
//创建 i > 5
var bin = Expression.GreaterThan(parameter,constant);
//获取Lambda表达式
var lambda=Expression.Lambda>(bin,parameter);
//取得查询结果
var query = ints.Where(lambda.Compile());
BinaryExpression condition = null;
//要构造的表达式i==1||i==2||i==3.....
for (int i = 0; i < ints.Length; i++)
{
ConstantExpression ce = Expression.Constant(i);
if (condition == null)
{
condition = Expression.Equal(parameter, ce);
}
else
{
var right = Expression.Equal(parameter, ce);
condition = Expression.Or(condition, right);
}
}
Expression> lambda = Expression.Lambda>(condition, parameter);
绍一下如何对实体类进行构造。
//p => p.Name == "1" && p.Address == "2"
ParameterExpression parameter1 = Expression.Parameter(typeof(Person), "p");
MemberExpression member1 = Expression.PropertyOrField(parameter1, "Name");
MemberExpression member2 = Expression.PropertyOrField(parameter1, "Address"),
ConstantExpression constant1 = Expression.Constant("郑浩");
ConstantExpression constant2 = Expression.Constant("河北");
var query1 = Expression.Equal(member1, constant1);//Equal等于;GreaterThanOrEqual大于;LessThanOrEqual小于
var query2 = Expression.Equal(member2, constant2);
var query = Expression.And(query1, query2);//and 与;or或
var lambda1 = Expression.Lambda>(query, parameter1);
var list = MethodExtend.GetUser(lambda1.Compile());
1)创建表达式的开始部分:p=>
2、3)创建我们要查询的字段:p.Name和p.Address
4、5)给给变量赋值,这些值和变量可以任意匹配
6、7)匹配查询条件和对应的值:p.Name=="郑浩";p.Address=="河北"
8、9)连接查询条件;p.Name=="郑浩"&&p.Address=="河北"
10)创建最后的查询条件:p=>p.Name=="郑浩"&&p.Address=="河北"
11)最后执行查询条件
我首先创建了一个接口,因为这个功能不是我自己使用,还有别的模块也需要这个功能;
namespace Seagull2.Investment.WebApi
{
///
/// 可实现表达式接口
///
public interface IExpressionable where T : class
{
///
/// 创建表达式
///
///
Expression> CreateExpression();
}
}
我将创建Landa表达式的部分放在module中,这个module是和界面对应,接收界面传递参数,代码如下:
public class RealEstateProjectCondition : IExpressionable
{
///
/// 项目所在省份
///
public string ProjectOfProvince { get; set; }
///
/// 项目所在城市
///
public string ProjectOfCity { get; set; }
///
/// 项目业态名称
///
public string ProjectFormatName { get; set; }
///
/// 所属业务团队
///
public string BusiGroup { get; set; }
///
/// 项目所处阶段
///
public string PrjStageCode { get; set; }
///
/// 申请起始日期
///
public DateTimeOffset? ApplyStartDate { get; set; }
///
/// 申请起始日期
///
public DateTimeOffset? ApplyEndDate { get; set; }
///
/// 基金规模(亿元)上线
///
public decimal? StartFundSize { get; set; }
///
/// 基金规模(亿元)下线
///
public decimal? EndFundSize { get; set; }
///
/// 创建房地产投资查询条件表达式
///
///
public Expression> CreateExpression()
{
ParameterExpression parameter = Expression.Parameter(typeof(View_RealEstateProject), "p");
//项目类型编码
ConstantExpression constantPrjTypeCode = Expression.Constant("A0BE01A2-1BE3-4AAE-8DE3-B84BB6B2A58A");
MemberExpression memberPrjTypeCode = Expression.PropertyOrField(parameter, "PrjTypeCode");
var query = Expression.Equal(memberPrjTypeCode, constantPrjTypeCode);
//项目所在省份
if (!string.IsNullOrEmpty(this.ProjectOfProvince))
{
ConstantExpression constantProjectOfProvince = Expression.Constant(this.ProjectOfProvince);
MemberExpression memberProjectOfCity = Expression.PropertyOrField(parameter, "ProjectOfProvince");
query = Expression.And(query, Expression.Equal(memberProjectOfCity, constantProjectOfProvince));
}
//项目所在城市
if (!string.IsNullOrEmpty(this.ProjectOfCity))
{
ConstantExpression constantProjectOfCity = Expression.Constant(this.ProjectOfCity);
MemberExpression memberProjectOfCity = Expression.PropertyOrField(parameter, "ProjectOfCity");
query = Expression.And(query, Expression.Equal(memberProjectOfCity, constantProjectOfCity));
}
//项目业态名称
if (!string.IsNullOrEmpty(this.ProjectFormatName))
{
ConstantExpression constantProjectFormatName = Expression.Constant(this.ProjectFormatName);
MemberExpression memberProjectFormatName = Expression.PropertyOrField(parameter, "ProjectFormatName");
query = Expression.And(query, Expression.Equal(memberProjectFormatName, constantProjectFormatName));
}
//所属业务团队
if (!string.IsNullOrEmpty(this.BusiGroup))
{
ConstantExpression constantBusiGroup = Expression.Constant(this.BusiGroup);
MemberExpression memberBusiGroup = Expression.PropertyOrField(parameter, "BusiGroup");
query = Expression.And(query, Expression.Equal(memberBusiGroup, constantBusiGroup));
}
//项目所处阶段
if (!string.IsNullOrEmpty(this.PrjStageCode))
{
ConstantExpression constantPrjStageCode = Expression.Constant(this.PrjStageCode);
MemberExpression memberPrjStageCode = Expression.PropertyOrField(parameter, "PrjStageCode");
query = Expression.And(query, Expression.Equal(memberPrjStageCode, constantPrjStageCode));
}
//申请开始时间
if (this.ApplyStartDate.HasValue)
{
ConstantExpression constantApplyStartDate = Expression.Constant(this.ApplyStartDate.Value);
MemberExpression memberApplyStartDate = Expression.PropertyOrField(parameter, "ApplyDate");
query = Expression.And(query, Expression.GreaterThanOrEqual(memberApplyStartDate, constantApplyStartDate));
}
//申请结束时间
if (this.ApplyEndDate.HasValue)
{
ConstantExpression constantApplyEndDate = Expression.Constant(this.ApplyEndDate.Value);
MemberExpression memberApplyEndDate = Expression.PropertyOrField(parameter, "ApplyDate");
query = Expression.And(query, Expression.LessThanOrEqual(memberApplyEndDate, constantApplyEndDate));
}
//投资规模(亿元)上线
if (this.StartFundSize.HasValue)
{
ConstantExpression constantStartFundSize = Expression.Constant(this.StartFundSize.Value);
MemberExpression memberStartFundSize = Expression.PropertyOrField(parameter, "FundSize");
query = Expression.And(query, Expression.GreaterThanOrEqual(memberStartFundSize, constantStartFundSize));
}
//投资规模(亿元)下线
if (this.EndFundSize.HasValue)
{
ConstantExpression constantEndFundSize = Expression.Constant(this.EndFundSize.Value);
MemberExpression memberEndFundSize = Expression.PropertyOrField(parameter, "FundSize");
query = Expression.And(query, Expression.LessThanOrEqual(memberEndFundSize, constantEndFundSize));
}
//版本结束时间
ConstantExpression constantVesionEndTime = Expression.Constant(null);
MemberExpression memberVesionEndTime = Expression.PropertyOrField(parameter, "VersionEndTime");
query = Expression.And(query, Expression.Equal(memberVesionEndTime, constantVesionEndTime));
//有效性
ConstantExpression constantValidStatus = Expression.Constant(true);
MemberExpression memberValidStatus = Expression.PropertyOrField(parameter, "ValidStatus");
query = Expression.And(query, Expression.Equal(memberValidStatus, constantValidStatus));
return Expression.Lambda>(query, parameter);
}
}
}
service代码:
public List LoadView_RealEstateProject(RealEstateProjectCondition condition)
{
using (var db = new InvestmentDbContext())
{
return db.View_RealEstateProject.Where(condition.CreateExpression()).ToList();
}
}
controller代码:
[HttpPost, HttpGet]
public IHttpActionResult LoadQueryResult(RealEstateProjectCondition condition)
{
return Json(_realEstabDasbordService.LoadView_RealEstateProject(condition));
}
关于动态创建Lamda表达式就给大家介绍到这,通过动态创建表达式非常方便实现高级查询,和拼接sql来说这
还是非常简单的,并且出错的几率大大降低,所以我没有采用他们类似功能的实现,所以说我们在实现某些需求的时
候需要我们好好考虑在下手写代码,能参考的东西不一定是最合适的,还需要我们自己探索一些,希望给大家带来帮
助。