注: 有参考文章<https://blog.csdn.net/leewhoee/article/details/8968023>;
以及文章<http://www.albahari.com/nutshell/predicatebuilder.aspx>
此文只为记录,用作之后的借鉴
public static class ExpressionsBuilderExtend
{
public static Expression<Func<T, bool>> True<T>() { return x => true; }
public static Expression<Func<T, bool>> False<T>() { return x => false; }
/// <summary>
/// Lambda表达式拼接 Or 语句,此方法适用于Linq to entities,不适用于Linq to sql
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)
{
return left.Compose(right, Expression.Or);
}
/// <summary>
/// Lambda表达式拼接 And 语句,此方法适用于Linq to entities,不适用于Linq to sql
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)
{
return left.Compose(right, Expression.And);
}
/// <summary>
/// Lambda表达式拼接 And 语句,此方法适用于Linq to sql,不适用于Linq to entities
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> And4Sql<T>(this Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)
{
var invokedExpr = Expression.Invoke(right, left.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(left.Body, invokedExpr), left.Parameters);
}
/// <summary>
/// Lambda表达式拼接 Or 语句,此方法适用于Linq to sql,不适用于Linq to entities
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> Or4Sql<T>(this Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)
{
var invokedExpr = Expression.Invoke(right, left.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>(Expression.OrElse(left.Body, invokedExpr), left.Parameters);
}
/// <summary>
/// Lambda表达式拼接
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="left"></param>
/// <param name="right"></param>
/// <param name="merge"></param>
/// <returns></returns>
public static Expression<T> Compose<T>(this Expression<T> left, Expression<T> right, Func<Expression, Expression, Expression> merge)
{
var map = left.Parameters.Select((leftParam, i) => new { leftParam, rightParam = right.Parameters[i] }).ToDictionary(x => x.rightParam, y => y.leftParam);
var rightBody = ParameterRebinder.ReplaceParameters(map, right.Body);
return Expression.Lambda<T>(merge(left.Body, rightBody), left.Parameters);
}
}
public class ParameterRebinder : ExpressionVisitor
{
private readonly Dictionary<ParameterExpression, ParameterExpression> map;
/// <summary>
///
/// </summary>
/// <param name="map"></param>
public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
{
this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
}
/// <summary>
///
/// </summary>
/// <param name="map"></param>
/// <param name="exp"></param>
/// <returns></returns>
public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
{
return new ParameterRebinder(map).Visit(exp);
}
/// <summary>
///
/// </summary>
/// <param name="x"></param>
/// <returns></returns>
protected override Expression VisitParameter(ParameterExpression x)
{
ParameterExpression replacement;
if (map.TryGetValue(x, out replacement))
{
x = replacement;
}
return base.VisitParameter(x);
}
}
linq to entities 的实际使用Demo
#region 组织查询条件
Expression<Func<S_P_Client, bool>> expression = x => x.IsDeleted.Equals("0");
if (string.IsNullOrEmpty(dto.KeyWord) == false)
{
Expression<Func<S_P_Client, bool>> expRight = x => (x.ClientName.Contains(dto.KeyWord) || x.ClientEnglishName.Contains(dto.KeyWord));
expression = expression.And(expRight);//expression1 = expression1.And();
}
if (string.IsNullOrEmpty(dto.CompanyNature) == false)
expression = expression.And(x => x.CompanyNature.Equals(dto.CompanyNature));
if (string.IsNullOrEmpty(dto.Status) == false)
expression = expression.And(x => x.Status.Equals(dto.Status));
if (string.IsNullOrEmpty(dto.Trade) == false)
expression = expression.And(x => x.Trade.Equals(dto.Trade));
#endregion
using (ProjectEntities entities = new ProjectEntities())
{
var all = entities.Set<S_P_Client>().Where(expression).AsQueryable().OrderBy(dto.sort, dto.order.ToLower().Equals("asc")).ToList();
var rows = all.Skip(dto.offset).Take(dto.limit).ToList();
return Json(new { total = all.Count(), rows = rows }, JsonRequestBehavior.AllowGet);
}
linq to sql 实际使用Demo
#region 查询内容
var queryT = from m in contractList.AsQueryable()
join tt in tempLst.AsQueryable() on m.ContractID equals tt.ContractID into temp
from tg in temp.DefaultIfEmpty()
select new ProjectContractListDto
{
/***省略**/
};
#region 组织lambda表达式
Expression<Func<ProjectContractListDto, bool>> expression = x => true;
if (string.IsNullOrEmpty(dto.KeyWord) == false)
{
Expression<Func<ProjectContractListDto, bool>> expressionOr = (x => x.ContractID.Contains(dto.KeyWord) || x.ContractName.Contains(dto.KeyWord) || x.SupplierName.Contains(dto.KeyWord));
expression = expression.And4Sql(expressionOr);
}
#endregion
var list = queryT.Where(expression).AsQueryable().OrderBy(dto.sort, dto.order.ToLower().Equals("asc")).ToList();
var rows = list.Skip(dto.offset).Take(dto.limit).ToList();
return Json(new { total = list.Count(), rows = rows }, JsonRequestBehavior.AllowGet);
#endregion