141 lines
4.7 KiB
C#
141 lines
4.7 KiB
C#
using PoweredSoft.DynamicLinq.Helpers;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Linq.Expressions;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace PoweredSoft.DynamicLinq.Fluent
|
|
{
|
|
public partial class WhereBuilder : IQueryBuilder
|
|
{
|
|
public IQueryable Query { get; set; }
|
|
public Type QueryableType { get; set; }
|
|
public List<WhereBuilderCondition> Filters { get; protected set; } = new List<WhereBuilderCondition>();
|
|
|
|
public WhereBuilder(IQueryable query)
|
|
{
|
|
Query = query;
|
|
QueryableType = query.ElementType;
|
|
}
|
|
|
|
public bool IsNullCheckingEnabled { get; protected set; } = false;
|
|
|
|
public virtual WhereBuilder NullChecking(bool check = true)
|
|
{
|
|
IsNullCheckingEnabled = check;
|
|
return this;
|
|
}
|
|
|
|
public virtual WhereBuilder Compare(string path, ConditionOperators conditionOperators, object value,
|
|
QueryConvertStrategy convertStrategy = QueryConvertStrategy.ConvertConstantToComparedPropertyOrField,
|
|
bool and = true, QueryCollectionHandling collectionHandling = QueryCollectionHandling.Any, StringComparison? stringComparision = null)
|
|
{
|
|
Filters.Add(new WhereBuilderCondition
|
|
{
|
|
And = and,
|
|
ConditionOperator = conditionOperators,
|
|
Path = path,
|
|
Value = value,
|
|
ConvertStrategy = convertStrategy,
|
|
CollectionHandling = collectionHandling,
|
|
StringComparisation = stringComparision
|
|
});
|
|
|
|
return this;
|
|
}
|
|
|
|
public virtual WhereBuilder SubQuery(Action<WhereBuilder> subQuery, bool and = true)
|
|
{
|
|
// create query builder for same type.
|
|
var qb = new WhereBuilder(Query);
|
|
qb.NullChecking(IsNullCheckingEnabled);
|
|
|
|
// callback.
|
|
subQuery(qb);
|
|
|
|
// create a query part.
|
|
var part = new WhereBuilderCondition();
|
|
part.And = and;
|
|
part.Conditions = qb.Filters;
|
|
Filters.Add(part);
|
|
|
|
//return self.
|
|
return this;
|
|
}
|
|
|
|
public virtual IQueryable Build()
|
|
{
|
|
// the query.
|
|
var query = Query;
|
|
|
|
if (Filters == null || Filters?.Count() == 0)
|
|
return query;
|
|
|
|
// shared parameter.
|
|
var sharedParameter = Expression.Parameter(QueryableType, "t");
|
|
|
|
// build the expression.
|
|
var filterExpressionMerged = BuildConditionExpression(sharedParameter, Filters);
|
|
|
|
// create the where expression.
|
|
var whereExpression = Expression.Call(typeof(Queryable), "Where", new[] { query.ElementType }, query.Expression, filterExpressionMerged);
|
|
|
|
// lets see what happens here.
|
|
query = query.Provider.CreateQuery(whereExpression);
|
|
|
|
return query;
|
|
}
|
|
|
|
protected virtual Expression BuildConditionExpression(ParameterExpression parameter, List<WhereBuilderCondition> filters)
|
|
{
|
|
Expression temp = null;
|
|
|
|
filters.ForEach(filter =>
|
|
{
|
|
Expression innerExpression;
|
|
if (filter.Conditions?.Any() == true)
|
|
innerExpression = BuildConditionExpression(parameter, filter.Conditions);
|
|
else
|
|
innerExpression = BuildConditionExpression(parameter, filter);
|
|
|
|
if (temp == null)
|
|
{
|
|
temp = innerExpression;
|
|
}
|
|
else
|
|
{
|
|
var body = ((LambdaExpression)temp).Body;
|
|
var innerEpressionBody = ((LambdaExpression)innerExpression).Body;
|
|
|
|
if (filter.And)
|
|
temp = Expression.Lambda(Expression.AndAlso(body, innerEpressionBody), parameter);
|
|
else
|
|
temp = Expression.Lambda(Expression.OrElse(body, innerEpressionBody), parameter);
|
|
}
|
|
|
|
});
|
|
|
|
return temp;
|
|
}
|
|
|
|
protected virtual Expression BuildConditionExpression(ParameterExpression parameter, WhereBuilderCondition filter)
|
|
{
|
|
var ret = QueryableHelpers.CreateConditionExpression(
|
|
parameter.Type,
|
|
filter.Path,
|
|
filter.ConditionOperator,
|
|
filter.Value,
|
|
filter.ConvertStrategy,
|
|
filter.CollectionHandling,
|
|
parameter: parameter,
|
|
nullChecking: IsNullCheckingEnabled,
|
|
stringComparision: filter.StringComparisation
|
|
);
|
|
|
|
return ret;
|
|
}
|
|
}
|
|
}
|