dotnet-dynamic-query/PoweredSoft.DynamicQuery/QueryHandler.cs

131 lines
4.7 KiB
C#
Raw Normal View History

2018-10-18 21:52:05 -04:00
using System;
2018-10-17 22:14:21 -04:00
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
2018-10-18 21:52:05 -04:00
using PoweredSoft.DynamicLinq;
2018-10-21 14:15:21 -04:00
using PoweredSoft.DynamicLinq.Fluent;
2018-10-18 21:52:05 -04:00
using PoweredSoft.DynamicQuery.Core;
2018-10-17 22:14:21 -04:00
namespace PoweredSoft.DynamicQuery
{
2018-10-18 21:52:05 -04:00
public class QueryHandler : QueryHandlerBase, IQueryHandler
2018-10-17 22:14:21 -04:00
{
2018-10-18 21:52:05 -04:00
internal MethodInfo ExecuteGeneric = typeof(QueryHandler).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic).First(t => t.Name == "Execute" && t.IsGenericMethod);
internal IQueryExecutionResult ExecuteReflected() => (IQueryExecutionResult)ExecuteGeneric.MakeGenericMethod(QueryableUnderlyingType).Invoke(this, new object[]{});
2018-10-17 22:14:21 -04:00
2018-10-18 21:52:05 -04:00
protected virtual IQueryExecutionResult Execute<T>()
2018-10-17 22:14:21 -04:00
{
2018-10-18 21:52:05 -04:00
ApplyIncludeStrategyInterceptors<T>();
ApplyBeforeFilterInterceptors<T>();
2018-10-17 22:14:21 -04:00
ApplyFilters<T>();
2018-10-18 21:52:05 -04:00
return HasGrouping ? ExecuteGrouping<T>() : ExecuteNoGrouping<T>();
2018-10-17 22:14:21 -04:00
}
2018-10-18 21:52:05 -04:00
protected virtual IQueryExecutionResult ExecuteGrouping<T>()
2018-10-17 22:14:21 -04:00
{
2018-10-19 17:44:13 -04:00
var result = new GroupedQueryExecutionResult();
result.TotalRecords = CurrentQueryable.LongCount();
2018-10-21 14:15:21 -04:00
// intercept groups in advance to avoid doing it more than once :)
var finalGroups = Criteria.Groups.Select(g => InterceptGroup<T>(g)).ToList();
// get the aggregates.
List<List<DynamicClass>> aggregateResults = null;
if (Criteria.Aggregates.Any())
2018-10-19 17:44:13 -04:00
{
2018-10-21 14:15:21 -04:00
var previousGroups = new List<IGroup>();
aggregateResults = finalGroups.Select(fg =>
2018-10-19 17:44:13 -04:00
{
2018-10-21 14:15:21 -04:00
var groupExpression = CurrentQueryable.GroupBy(QueryableUnderlyingType, gb =>
{
previousGroups.ForEach(pg =>
{
var previousGroupCleanedPath = pg.Path.Replace(".", "");
gb.Path(pg.Path, $"Key_{previousGroupCleanedPath}");
});
var cleanedPath = fg.Path.Replace(".", "");
gb.Path(fg.Path, $"Key_{cleanedPath}");
});
2018-10-19 17:44:13 -04:00
2018-10-21 14:15:21 -04:00
var selectExpression = groupExpression.Select(sb =>
2018-10-19 17:44:13 -04:00
{
2018-10-21 14:15:21 -04:00
previousGroups.ForEach(pg => sb.Key(pg.Path));
sb.Key(fg.Path);
Criteria.Aggregates.ForEach(a =>
{
var selectType = ResolveSelectFrom(a.Type);
var pathCleaned = a.Path?.Replace(".", "");
sb.Aggregate(a.Path, selectType, $"Agg_{a.Type}_{pathCleaned}");
});
2018-10-19 17:44:13 -04:00
});
2018-10-21 14:15:21 -04:00
var aggregateResult = selectExpression.ToDynamicClassList();
previousGroups.Add(fg);
return aggregateResult;
}).ToList();
}
// sorting.
finalGroups.ForEach(fg =>
{
Criteria.Sorts.Insert(0, new Sort()
{
Path = fg.Path,
Ascending = fg.Ascending
2018-10-19 17:44:13 -04:00
});
});
2018-10-21 14:15:21 -04:00
ApplySorting<T>();
ApplyPaging<T>();
// now get the data grouped.
CurrentQueryable = CurrentQueryable.GroupBy(QueryableUnderlyingType, gb => finalGroups.ForEach(fg => gb.Path(fg.Path)));
CurrentQueryable = CurrentQueryable.Select(sb =>
{
finalGroups.ForEach(fg => sb.Key(fg.Path));
sb.ToList("Records");
});
var temp = CurrentQueryable.ToDynamicClassList();
2018-10-19 17:44:13 -04:00
return result;
2018-10-17 22:14:21 -04:00
}
2018-10-19 17:44:13 -04:00
2018-10-21 14:15:21 -04:00
2018-10-18 21:52:05 -04:00
protected virtual IQueryExecutionResult ExecuteNoGrouping<T>()
2018-10-17 22:14:21 -04:00
{
2018-10-18 21:52:05 -04:00
var result = new QueryExecutionResult();
2018-10-17 22:14:21 -04:00
2018-10-18 21:52:05 -04:00
// total records.
result.TotalRecords = CurrentQueryable.LongCount();
2018-10-17 22:14:21 -04:00
2018-10-18 21:52:05 -04:00
// sorts and paging.
2018-10-21 14:15:21 -04:00
ApplySorting<T>();
ApplyPaging<T>();
2018-10-18 21:52:05 -04:00
// the data.
result.Data = CurrentQueryable.ToObjectList();
2018-10-17 22:14:21 -04:00
2018-10-18 21:52:05 -04:00
// if there is paging.
if (HasPaging)
{
if (result.TotalRecords < Criteria.PageSize)
result.NumberOfPages = 1;
else
result.NumberOfPages = result.TotalRecords / Criteria.PageSize + (result.TotalRecords % Criteria.PageSize != 0 ? 1 : 0);
}
2018-10-17 22:14:21 -04:00
2018-10-18 21:52:05 -04:00
return result;
2018-10-17 22:14:21 -04:00
}
2018-10-18 21:52:05 -04:00
public virtual IQueryExecutionResult Execute(IQueryable queryable, IQueryCriteria criteria)
2018-10-17 22:14:21 -04:00
{
Reset(queryable, criteria);
2018-10-18 21:52:05 -04:00
return ExecuteReflected();
2018-10-17 22:14:21 -04:00
}
}
}