|
|
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Linq;
|
|
|
using System.Linq.Expressions;
|
|
|
using AddWhere;
|
|
|
|
|
|
namespace LinqDemo
|
|
|
{
|
|
|
public static class QueryBuilder
|
|
|
{
|
|
|
public static IQueryBuilder<T> Create<T>()
|
|
|
{
|
|
|
return new QueryBuilder<T>();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
class QueryBuilder<T> : IQueryBuilder<T>
|
|
|
{
|
|
|
private Expression<Func<T, bool>> predicate;
|
|
|
Expression<Func<T, bool>> IQueryBuilder<T>.Expression
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
return predicate;
|
|
|
}
|
|
|
set
|
|
|
{
|
|
|
predicate = value;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//public List<ParameterExpression> Parameters { get; set; }
|
|
|
|
|
|
public QueryBuilder()
|
|
|
{
|
|
|
predicate = PredicateExtensions.True<T>();
|
|
|
//Parameters = new List<ParameterExpression>();
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 动态查询条件创建者
|
|
|
/// </summary>
|
|
|
/// <typeparam name="T"></typeparam>
|
|
|
public interface IQueryBuilder<T>
|
|
|
{
|
|
|
Expression<Func<T, bool>> Expression { get; set; }
|
|
|
//List<ParameterExpression> Parameters { get; set; }
|
|
|
}
|
|
|
|
|
|
public static class IQueryBuilderExtensions
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// 建立 Between 查询条件
|
|
|
/// </summary>
|
|
|
/// <typeparam name="T">实体</typeparam>
|
|
|
/// <param name="q">动态查询条件创建者</param>
|
|
|
/// <param name="property">属性</param>
|
|
|
/// <param name="from">开始值</param>
|
|
|
/// <param name="to">结束值</param>
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public static IQueryBuilder<T> Between<T, P>(this IQueryBuilder<T> q, Expression<Func<T, P>> property, P from, P to)
|
|
|
{
|
|
|
|
|
|
var parameter = property.GetParameters();
|
|
|
|
|
|
var constantFrom = Expression.Constant(from);
|
|
|
|
|
|
var constantTo = Expression.Constant(to);
|
|
|
|
|
|
Type type = typeof(P);
|
|
|
|
|
|
Expression nonNullProperty = property.Body;
|
|
|
|
|
|
//如果是Nullable<X>类型,则转化成X类型
|
|
|
|
|
|
if (IsNullableType(type))
|
|
|
{
|
|
|
|
|
|
type = GetNonNullableType(type);
|
|
|
|
|
|
nonNullProperty = Expression.Convert(property.Body, type);
|
|
|
|
|
|
}
|
|
|
|
|
|
System.Linq.Expressions.BinaryExpression c1=null;
|
|
|
System.Linq.Expressions.BinaryExpression c2=null;
|
|
|
System.Linq.Expressions.BinaryExpression c=null;
|
|
|
if (from != null)
|
|
|
c1 = Expression.GreaterThanOrEqual(nonNullProperty, constantFrom);
|
|
|
if (to != null)
|
|
|
c2 = Expression.LessThanOrEqual(nonNullProperty, constantTo);
|
|
|
|
|
|
if(from !=null && to != null)
|
|
|
c = Expression.AndAlso(c1, c2);
|
|
|
|
|
|
if (from != null && to == null)
|
|
|
c = c1;
|
|
|
|
|
|
if (from == null && to != null)
|
|
|
c = c2;
|
|
|
|
|
|
Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(c, parameter);
|
|
|
|
|
|
q.Expression = q.Expression.And(lambda);
|
|
|
|
|
|
return q;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 建立 Like ( 模糊 ) 查询条件
|
|
|
/// </summary>
|
|
|
/// <typeparam name="T">实体</typeparam>
|
|
|
/// <param name="q">动态查询条件创建者</param>
|
|
|
/// <param name="property">属性</param>
|
|
|
/// <param name="value">查询值</param>
|
|
|
/// <returns></returns>
|
|
|
#region
|
|
|
public static IQueryBuilder<T> Like<T>(this IQueryBuilder<T> q, Expression<Func<T, string>> property, string value)
|
|
|
{
|
|
|
|
|
|
value = value.Trim();
|
|
|
|
|
|
if (!string.IsNullOrEmpty(value))
|
|
|
{
|
|
|
|
|
|
var parameter = property.GetParameters();
|
|
|
Expression<Func<T, bool>> lambda = null;
|
|
|
//MethodCallExpression methodExp = Expression.Call(property.Body,
|
|
|
// typeof(string).GetMethod("Contains", new Type[] { typeof(string) }),
|
|
|
// Expression.Constant(value)
|
|
|
//);
|
|
|
var c = typeof(string).GetMethod("IndexOf", new[] { typeof(string) });
|
|
|
MethodCallExpression methodExp = Expression.Call(property.Body,
|
|
|
c,
|
|
|
Expression.Constant(value)
|
|
|
);
|
|
|
var condition = Expression.NotEqual(Expression.Convert(methodExp, typeof(int)), Expression.Constant(-1));
|
|
|
|
|
|
lambda = Expression.Lambda<Func<T, bool>>(condition, parameter);
|
|
|
//MethodCallExpression methodExp = Expression.Call(null, typeof(SqlMethods).GetMethod("Like",
|
|
|
|
|
|
// new Type[] { typeof(string), typeof(string) }), property.Body, constant);
|
|
|
|
|
|
//Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(methodExp, parameter);
|
|
|
//Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(methodExp, parameter);
|
|
|
|
|
|
|
|
|
q.Expression = q.Expression.And(lambda);
|
|
|
|
|
|
}
|
|
|
|
|
|
return q;
|
|
|
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
|
/// 建立 OrLike ( 模糊 ) 查询条件
|
|
|
/// </summary>
|
|
|
/// <typeparam name="T">实体</typeparam>
|
|
|
/// <param name="q">动态查询条件创建者</param>
|
|
|
/// <param name="property">属性</param>
|
|
|
/// <param name="value">查询值</param>
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private static Expression<Func<T, bool>> OrLike<T>(this IQueryBuilder<T> q, Expression<Func<T, string>> property, string value)
|
|
|
{
|
|
|
#region
|
|
|
//List<Expression> Expressions = new List<Expression>();
|
|
|
var parameter = property.GetParameters();
|
|
|
Expression<Func<T, bool>> lambda = null;
|
|
|
|
|
|
if (!string.IsNullOrEmpty(value))
|
|
|
{
|
|
|
//var propertyBody = GetMemberExpression(q, property);
|
|
|
MethodCallExpression methodExp = Expression.Call(property.Body,
|
|
|
typeof(string).GetMethod("Contains", new Type[] { typeof(string) }),
|
|
|
Expression.Constant(value)
|
|
|
//typeof(LinqToSqlShared).GetMethod("IndexOf", new[] { typeof(string) }), Expression.Constant(value)
|
|
|
);
|
|
|
//Expressions.Add(methodExp);
|
|
|
//var condition = Expression.GreaterThan(methodExp, Expression.Constant(0));
|
|
|
|
|
|
lambda = Expression.Lambda<Func<T, bool>>(methodExp, parameter);
|
|
|
}
|
|
|
|
|
|
//Expression<Func<T, bool>> lambda = null;
|
|
|
//if (Expressions.Count != 0)
|
|
|
//{
|
|
|
// Expression expression = Expressions.Aggregate((e1, e2) => Expression.Or(e1, e2));
|
|
|
// lambda = Expression.Lambda<Func<T, bool>>(expression, parameter);
|
|
|
// //q.Expression = q.Expression.And(lambda);
|
|
|
|
|
|
//}
|
|
|
|
|
|
return lambda;
|
|
|
#endregion
|
|
|
}
|
|
|
|
|
|
|
|
|
private static Expression<Func<T, bool>> OrCharIndex<T>(this IQueryBuilder<T> q, Expression<Func<T, string>> property, string value)
|
|
|
{
|
|
|
#region
|
|
|
|
|
|
var parameter = property.GetParameters();
|
|
|
Expression<Func<T, bool>> lambda = null;
|
|
|
|
|
|
if (!string.IsNullOrEmpty(value))
|
|
|
{
|
|
|
var c = typeof(string).GetMethod("IndexOf", new[] { typeof(string) });
|
|
|
MethodCallExpression methodExp = Expression.Call(property.Body,
|
|
|
c,
|
|
|
Expression.Constant(value)
|
|
|
);
|
|
|
var condition = Expression.NotEqual(Expression.Convert(methodExp, typeof(int)), Expression.Constant(-1));
|
|
|
|
|
|
lambda = Expression.Lambda<Func<T, bool>>(condition, parameter);
|
|
|
}
|
|
|
|
|
|
return lambda;
|
|
|
#endregion
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 建立 Equals ( 相等 ) 查询条件
|
|
|
/// </summary>
|
|
|
/// <typeparam name="T">实体</typeparam>
|
|
|
/// <param name="q">动态查询条件创建者</param>
|
|
|
/// <param name="property">属性</param>
|
|
|
/// <param name="value">查询值</param>
|
|
|
/// <returns></returns>
|
|
|
public static IQueryBuilder<T> Equals<T, P>(this IQueryBuilder<T> q, Expression<Func<T, P>> property, P value)
|
|
|
{
|
|
|
|
|
|
var parameter = property.GetParameters();
|
|
|
|
|
|
var constant = Expression.Constant(value);
|
|
|
|
|
|
Type type = typeof(P);
|
|
|
|
|
|
Expression nonNullProperty = property.Body;
|
|
|
|
|
|
//如果是Nullable<X>类型,则转化成X类型
|
|
|
|
|
|
if (IsNullableType(type))
|
|
|
{
|
|
|
|
|
|
type = GetNonNullableType(type);
|
|
|
|
|
|
nonNullProperty = Expression.Convert(property.Body, type);
|
|
|
|
|
|
}
|
|
|
|
|
|
var methodExp = Expression.Equal(nonNullProperty, constant);
|
|
|
|
|
|
Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(methodExp, parameter);
|
|
|
|
|
|
q.Expression = q.Expression.And(lambda);
|
|
|
|
|
|
return q;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 建立 In 查询条件
|
|
|
/// </summary>
|
|
|
/// <typeparam name="T">实体</typeparam>
|
|
|
/// <param name="q">动态查询条件创建者</param>
|
|
|
/// <param name="property">属性</param>
|
|
|
/// <param name="valuse">查询值</param>
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public static IQueryBuilder<T> In<T, P>(this IQueryBuilder<T> q, Expression<Func<T, P>> property, IEnumerable<P> values)
|
|
|
{
|
|
|
|
|
|
if (values != null )
|
|
|
{
|
|
|
|
|
|
var parameter = property.GetParameters();
|
|
|
|
|
|
var constant = Expression.Constant(values);
|
|
|
|
|
|
Type type = typeof(P);
|
|
|
|
|
|
Expression nonNullProperty = property.Body;
|
|
|
|
|
|
//如果是Nullable<X>类型,则转化成X类型
|
|
|
|
|
|
if (IsNullableType(type))
|
|
|
{
|
|
|
|
|
|
type = GetNonNullableType(type);
|
|
|
|
|
|
nonNullProperty = Expression.Convert(property.Body, type);
|
|
|
|
|
|
}
|
|
|
|
|
|
Expression<Func<IEnumerable<P>, P, bool>> InExpression = (list, el) => list.Contains(el);
|
|
|
|
|
|
var methodExp = InExpression;
|
|
|
|
|
|
var invoke = Expression.Invoke(methodExp, constant, property.Body);
|
|
|
|
|
|
Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(invoke, parameter);
|
|
|
|
|
|
q.Expression = q.Expression.And(lambda);
|
|
|
|
|
|
}
|
|
|
|
|
|
return q;
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 建立 NotIn 查询条件
|
|
|
/// </summary>
|
|
|
/// <typeparam name="T">实体</typeparam>
|
|
|
/// <param name="q">动态查询条件创建者</param>
|
|
|
/// <param name="property">属性</param>
|
|
|
/// <param name="valuse">查询值</param>
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public static IQueryBuilder<T> NotIn<T, P>(this IQueryBuilder<T> q, Expression<Func<T, P>> property, IEnumerable<P> values)
|
|
|
{
|
|
|
|
|
|
if (values != null )
|
|
|
{
|
|
|
|
|
|
var parameter = property.GetParameters();
|
|
|
|
|
|
var constant = Expression.Constant(values);
|
|
|
|
|
|
Type type = typeof(P);
|
|
|
|
|
|
Expression nonNullProperty = property.Body;
|
|
|
|
|
|
//如果是Nullable<X>类型,则转化成X类型
|
|
|
|
|
|
if (IsNullableType(type))
|
|
|
{
|
|
|
|
|
|
type = GetNonNullableType(type);
|
|
|
|
|
|
nonNullProperty = Expression.Convert(property.Body, type);
|
|
|
|
|
|
}
|
|
|
|
|
|
Expression<Func<IEnumerable<P>, P, bool>> InExpression = (list, el) => !list.Contains(el);
|
|
|
|
|
|
var methodExp = InExpression;
|
|
|
|
|
|
var invoke = Expression.Invoke(methodExp, constant, property.Body);
|
|
|
|
|
|
Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(invoke, parameter);
|
|
|
|
|
|
q.Expression = q.Expression.And(lambda);
|
|
|
|
|
|
}
|
|
|
|
|
|
return q;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// FullText查询,多字段 多字符串
|
|
|
/// </summary>
|
|
|
/// <typeparam name="T"></typeparam>
|
|
|
/// <param name="q"></param>
|
|
|
/// <param name="expression">支持1 2 3 以空格作为分隔符</param>
|
|
|
/// <param name="properties">查询字段属性 o => o.xxx1,o => o.xxx2...</param>
|
|
|
/// <returns></returns>
|
|
|
public static IQueryBuilder<T> FullText<T>(this IQueryBuilder<T> q, string expression, List<Expression<Func<T, string>>> properties)
|
|
|
{
|
|
|
if (string.IsNullOrEmpty(expression))
|
|
|
return q;
|
|
|
if (properties == null || properties.Count() == 0 )
|
|
|
return q;
|
|
|
|
|
|
string[] es = expression.Split(' ');
|
|
|
List<Expression<Func<T, bool>>> lambda1 = new List<Expression<Func<T,bool>>>();
|
|
|
foreach (var str in es)
|
|
|
{
|
|
|
List<Expression<Func<T, bool>>> lambda2 = new List<Expression<Func<T,bool>>>();
|
|
|
foreach (var property in properties)
|
|
|
{
|
|
|
var a = q.OrCharIndex(property, str);
|
|
|
|
|
|
if(a != null)
|
|
|
lambda2.Add(a);
|
|
|
}
|
|
|
if (lambda2.Count != 0)
|
|
|
lambda1.Add(lambda2.Aggregate((e1, e2) => e1.Or(e2)));
|
|
|
}
|
|
|
//var b = lambda1.Aggregate((e1, e2) => e1.Or(e2));
|
|
|
//q.Expression = q.Expression.And(b);
|
|
|
foreach (var b in lambda1)
|
|
|
q.Expression = q.Expression.And(b);
|
|
|
|
|
|
return q;
|
|
|
}
|
|
|
|
|
|
private static ParameterExpression[] GetParameters<T, S>(this Expression<Func<T, S>> expr)
|
|
|
{
|
|
|
return expr.Parameters.ToArray();
|
|
|
}
|
|
|
|
|
|
static bool IsNullableType(Type type)
|
|
|
{
|
|
|
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
|
|
|
}
|
|
|
|
|
|
|
|
|
static Type GetNonNullableType(Type type)
|
|
|
{
|
|
|
return type.GetGenericArguments()[0];
|
|
|
//return IsNullableType(type) ? type.GetGenericArguments()[0] : type;
|
|
|
}
|
|
|
|
|
|
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
|
|
|
{
|
|
|
foreach (T element in source)
|
|
|
action(element);
|
|
|
}
|
|
|
|
|
|
//EF参数重写
|
|
|
//private static Expression GetMemberExpression<T, P>(IQueryBuilder<T> q, Expression<Func<T, P>> property)
|
|
|
//{
|
|
|
// if (q.Parameters == null || q.Parameters.Count == 0)
|
|
|
// {
|
|
|
// property.Parameters.ForEach(
|
|
|
// p =>
|
|
|
// {
|
|
|
// q.Parameters.Add(p);
|
|
|
// }
|
|
|
// );
|
|
|
// return property.Body;
|
|
|
// }
|
|
|
|
|
|
// ParameterExpressionVisitor visitor = new ParameterExpressionVisitor(q.Parameters[0]);
|
|
|
|
|
|
// Expression memberExpr = visitor.ChangeParameter(property.Body);
|
|
|
|
|
|
// return memberExpr;
|
|
|
//}
|
|
|
|
|
|
//public class ParameterExpressionVisitor : ExpressionVisitor
|
|
|
//{
|
|
|
// private ParameterExpression newParameterExpression;
|
|
|
|
|
|
// public ParameterExpressionVisitor(ParameterExpression p)
|
|
|
// {
|
|
|
// newParameterExpression = p;
|
|
|
// }
|
|
|
|
|
|
// public Expression ChangeParameter(Expression exp)
|
|
|
// {
|
|
|
// return Visit(exp);
|
|
|
// }
|
|
|
|
|
|
// protected override Expression VisitParameter(ParameterExpression p)
|
|
|
// {
|
|
|
// return newParameterExpression;
|
|
|
// }
|
|
|
//}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|