EF扩展方法,方便动态查询
作者:互联网
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace EFDemo { /// <summary> /// Defines the <see cref="QueryExtention" />. /// </summary> public static class QueryExtention { /// <summary> /// The Where. /// </summary> /// <typeparam name="T">.</typeparam> /// <param name="source">The source<see cref="IQueryable{T}"/>.</param> /// <param name="whereConditions">The whereConditions<see cref="List{WhereCondition}"/>.</param> /// <returns>The <see cref="IQueryable{T}"/>.</returns> public static IQueryable<T> Where<T>(this IQueryable<T> source, List<WhereCondition> whereConditions) where T : class { foreach (var query in whereConditions) { source = source.Where(query.Filters.AsExpression<T>(query.Link)); } return source; } } /// <summary> /// Defines the Operators. /// </summary> public enum Operators { /// <summary> /// Defines the None. /// </summary> None = 0, /// <summary> /// Defines the Equal. /// </summary> Equal = 1, /// <summary> /// Defines the Contains. /// </summary> Contains = 2, /// <summary> /// Defines the StartWith. /// </summary> StartWith = 3, /// <summary> /// Defines the EndWidth. /// </summary> EndWidth = 4, /// <summary> /// Defines the Range. /// </summary> Range = 5, /// <summary> /// Defines the GreaterThan. /// </summary> GreaterThan = 6, /// <summary> /// Defines the GreaterThanOrEqual. /// </summary> GreaterThanOrEqual = 7, /// <summary> /// Defines the LessThan. /// </summary> LessThan = 8, /// <summary> /// Defines the LessThanOrEqual. /// </summary> LessThanOrEqual = 9, } /// <summary> /// Defines the ConditionLink. /// </summary> public enum ConditionLink { /// <summary> /// Defines the OrElse. /// </summary> OrElse = 1, /// <summary> /// Defines the AndAlso. /// </summary> AndAlso = 2 } /// <summary> /// Defines the <see cref="Query" />. /// </summary> public class Query { /// <summary> /// Gets or sets the Name. /// </summary> public string Name { get; set; } /// <summary> /// Gets or sets the Operator. /// </summary> public Operators Operator { get; set; } /// <summary> /// Gets or sets the Value. /// </summary> public object Value { get; set; } /// <summary> /// Gets or sets the ValueMin. /// </summary> public object ValueMin { get; set; } /// <summary> /// Gets or sets the ValueMax. /// </summary> public object ValueMax { get; set; } } /// <summary> /// Defines the <see cref="QueryCollection" />. /// </summary> public class QueryCollection : Collection<Query> { /// <summary> /// The AsExpression. /// </summary> /// <typeparam name="T">.</typeparam> /// <param name="condition">The condition<see cref="ConditionLink?"/>.</param> /// <returns>The <see cref="Expression{Func{T, bool}}"/>.</returns> public Expression<Func<T, bool>> AsExpression<T>(ConditionLink? condition = ConditionLink.OrElse) where T : class { Type targetType = typeof(T); TypeInfo typeInfo = targetType.GetTypeInfo(); var parameter = Expression.Parameter(targetType, "m"); Expression expression = null; Func<Expression, Expression, Expression> Append = (exp1, exp2) => { if (exp1 == null) { return exp2; } return (condition ?? ConditionLink.OrElse) == ConditionLink.OrElse ? Expression.OrElse(exp1, exp2) : Expression.AndAlso(exp1, exp2); }; foreach (var item in this) { var property = typeInfo.GetProperty(item.Name); if (property == null || !property.CanRead || (item.Operator != Operators.Range && item.Value == null) || (item.Operator == Operators.Range && item.ValueMin == null && item.ValueMax == null)) { continue; } Type realType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType; if (item.Value != null) { item.Value = Convert.ChangeType(item.Value, realType); } Expression<Func<object>> valueLamba = () => item.Value; switch (item.Operator) { case Operators.Equal: { expression = Append(expression, Expression.Equal(Expression.Property(parameter, item.Name), Expression.Convert(valueLamba.Body, property.PropertyType))); break; } case Operators.GreaterThan: { expression = Append(expression, Expression.GreaterThan(Expression.Property(parameter, item.Name), Expression.Convert(valueLamba.Body, property.PropertyType))); break; } case Operators.GreaterThanOrEqual: { expression = Append(expression, Expression.GreaterThanOrEqual(Expression.Property(parameter, item.Name), Expression.Convert(valueLamba.Body, property.PropertyType))); break; } case Operators.LessThan: { expression = Append(expression, Expression.LessThan(Expression.Property(parameter, item.Name), Expression.Convert(valueLamba.Body, property.PropertyType))); break; } case Operators.LessThanOrEqual: { expression = Append(expression, Expression.LessThanOrEqual(Expression.Property(parameter, item.Name), Expression.Convert(valueLamba.Body, property.PropertyType))); break; } case Operators.Contains: { //var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, Expression.Property(parameter, item.Name))); var contains = Expression.Call(Expression.Property(parameter, item.Name), "Contains", null, Expression.Convert(valueLamba.Body, property.PropertyType)); //expression = Append(expression, Expression.AndAlso(nullCheck, contains)); expression = Append(expression, contains); break; } case Operators.StartWith: { //var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, Expression.Property(parameter, item.Name))); var startsWith = Expression.Call(Expression.Property(parameter, item.Name), "StartsWith", null, Expression.Convert(valueLamba.Body, property.PropertyType)); expression = Append(expression, startsWith); break; } case Operators.EndWidth: { //var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, Expression.Property(parameter, item.Name))); var endsWith = Expression.Call(Expression.Property(parameter, item.Name), "EndsWith", null, Expression.Convert(valueLamba.Body, property.PropertyType)); expression = Append(expression, endsWith); break; } case Operators.Range: { Expression minExp = null, maxExp = null; if (item.ValueMin != null) { var minValue = Convert.ChangeType(item.ValueMin, realType); Expression<Func<object>> minValueLamda = () => minValue; minExp = Expression.GreaterThanOrEqual(Expression.Property(parameter, item.Name), Expression.Convert(minValueLamda.Body, property.PropertyType)); } if (item.ValueMax != null) { var maxValue = Convert.ChangeType(item.ValueMax, realType); Expression<Func<object>> maxValueLamda = () => maxValue; maxExp = Expression.LessThanOrEqual(Expression.Property(parameter, item.Name), Expression.Convert(maxValueLamda.Body, property.PropertyType)); } if (minExp != null && maxExp != null) { expression = Append(expression, Expression.AndAlso(minExp, maxExp)); } else if (minExp != null) { expression = Append(expression, minExp); } else if (maxExp != null) { expression = Append(expression, maxExp); } break; } } } if (expression == null) { return null; } return ((Expression<Func<T, bool>>)Expression.Lambda(expression, parameter)); } } /// <summary> /// Defines the <see cref="WhereCondition" />. /// </summary> public class WhereCondition { /// <summary> /// Gets or sets the Filters. /// </summary> public QueryCollection Filters { get; set; } /// <summary> /// Gets or sets the Link. /// </summary> public ConditionLink Link { get; set; } = ConditionLink.OrElse; } }
标签:Name,expression,EF,扩展,查询,item,null,Expression,Defines 来源: https://www.cnblogs.com/cyjngup/p/15642387.html