strongly typed returned interfaces, next is the async mode.

This commit is contained in:
David Lebee
2019-03-19 22:54:15 -05:00
parent 61642eee18
commit 9e6dc08e53
13 changed files with 316 additions and 260 deletions
@@ -0,0 +1,18 @@
using PoweredSoft.DynamicQuery.Core;
using System;
using System.Collections.Generic;
using System.Text;
namespace PoweredSoft.DynamicQuery.Extensions
{
public static class GroupResultExtensions
{
public static IQueryExecutionGroupResult<TRecord> GroupedResult<TRecord>(this IQueryExecutionResult<TRecord> source)
{
if (source is IQueryExecutionGroupResult<TRecord> ret)
return ret;
throw new Exception("this result is not a grouped result");
}
}
}
+33 -31
View File
@@ -4,6 +4,7 @@ using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using PoweredSoft.DynamicLinq;
using PoweredSoft.DynamicLinq.Fluent;
@@ -13,19 +14,15 @@ namespace PoweredSoft.DynamicQuery
{
public class QueryHandler : QueryHandlerBase, IQueryHandler
{
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[] { });
protected virtual IQueryExecutionResult Execute<T>()
protected virtual IQueryExecutionResult<TRecord> FinalExecute<TSource, TRecord>()
{
CommonBeforeExecute<T>();
return HasGrouping ? ExecuteGrouping<T>() : ExecuteNoGrouping<T>();
CommonBeforeExecute<TSource>();
return HasGrouping ? ExecuteGrouping<TSource, TRecord>() : ExecuteNoGrouping<TSource, TRecord>();
}
protected virtual IQueryExecutionResult ExecuteGrouping<T>()
protected virtual IQueryExecutionResult<TRecord> ExecuteGrouping<TSource, TRecord>()
{
var result = new QueryExecutionResult();
var result = new QueryGroupExecutionResult<TRecord>();
// preserve queryable.
var queryableAfterFilters = CurrentQueryable;
@@ -34,17 +31,17 @@ namespace PoweredSoft.DynamicQuery
CalculatePageCount(result);
// intercept groups in advance to avoid doing it more than once :)
var finalGroups = Criteria.Groups.Select(g => InterceptGroup<T>(g)).ToList();
var finalGroups = Criteria.Groups.Select(g => InterceptGroup<TSource>(g)).ToList();
// get the aggregates.
var aggregateResults = FetchAggregates<T>(finalGroups);
var aggregateResults = FetchAggregates<TSource>(finalGroups);
// sorting.
finalGroups.ForEach(fg => Criteria.Sorts.Insert(0, new Sort(fg.Path, fg.Ascending)));
// apply sorting and paging.
ApplySorting<T>();
ApplyPaging<T>();
ApplySorting<TSource>();
ApplyPaging<TSource>();
// create group & select expression.
CurrentQueryable = CurrentQueryable.GroupBy(QueryableUnderlyingType, gb => finalGroups.ForEach((fg, index) => gb.Path(fg.Path, $"Key_{index}")));
@@ -58,26 +55,26 @@ namespace PoweredSoft.DynamicQuery
var groupRecords = CurrentQueryable.ToDynamicClassList();
// now join them into logical collections
var lastLists = new List<List<object>>();
result.Data = RecursiveRegroup<T>(groupRecords, aggregateResults, Criteria.Groups.First(), lastLists);
var lastLists = new List<(List<TSource> source, IGroupQueryResult<TRecord> group)>();
result.Groups = RecursiveRegroup<TSource, TRecord>(groupRecords, aggregateResults, Criteria.Groups.First(), lastLists);
// intercept grouped by.
QueryInterceptToGrouped<T>(lastLists).Wait();
QueryInterceptToGrouped<TSource, TRecord>(lastLists).Wait();
result.Aggregates = CalculateTotalAggregate<T>(queryableAfterFilters);
result.Aggregates = CalculateTotalAggregate<TSource>(queryableAfterFilters);
return result;
}
protected virtual List<IAggregateResult> CalculateTotalAggregate<T>(IQueryable queryableAfterFilters)
protected virtual List<IAggregateResult> CalculateTotalAggregate<TSource>(IQueryable queryableAfterFilters)
{
if (!Criteria.Aggregates.Any())
return null;
IQueryable selectExpression = CreateTotalAggregateSelectExpression<T>(queryableAfterFilters);
IQueryable selectExpression = CreateTotalAggregateSelectExpression<TSource>(queryableAfterFilters);
var aggregateResult = selectExpression.ToDynamicClassList().FirstOrDefault();
return MaterializeCalculateTotalAggregateResult(aggregateResult);
}
protected virtual List<List<DynamicClass>> FetchAggregates<T>(List<IGroup> finalGroups)
protected virtual List<List<DynamicClass>> FetchAggregates<TSource>(List<IGroup> finalGroups)
{
if (!Criteria.Aggregates.Any())
return null;
@@ -85,7 +82,7 @@ namespace PoweredSoft.DynamicQuery
var previousGroups = new List<IGroup>();
var ret = finalGroups.Select(fg =>
{
IQueryable selectExpression = CreateFetchAggregateSelectExpression<T>(fg, previousGroups);
IQueryable selectExpression = CreateFetchAggregateSelectExpression<TSource>(fg, previousGroups);
var aggregateResult = selectExpression.ToDynamicClassList();
previousGroups.Add(fg);
return aggregateResult;
@@ -93,9 +90,9 @@ namespace PoweredSoft.DynamicQuery
return ret;
}
protected virtual IQueryExecutionResult ExecuteNoGrouping<T>()
protected virtual IQueryExecutionResult<TRecord> ExecuteNoGrouping<TSource, TRecord>()
{
var result = new QueryExecutionResult();
var result = new QueryExecutionResult<TRecord>();
// after filter queryable
var afterFilterQueryable = CurrentQueryable;
@@ -105,25 +102,30 @@ namespace PoweredSoft.DynamicQuery
CalculatePageCount(result);
// sorts and paging.
ApplySorting<T>();
ApplyPaging<T>();
ApplySorting<TSource>();
ApplyPaging<TSource>();
// data.
var entities = ((IQueryable<T>)CurrentQueryable).ToList();
var records = InterceptConvertTo<T>(entities).Result;
var entities = ((IQueryable<TSource>)CurrentQueryable).ToList();
var records = InterceptConvertTo<TSource, TRecord>(entities).Result;
result.Data = records;
// aggregates.
result.Aggregates = CalculateTotalAggregate<T>(afterFilterQueryable);
result.Aggregates = CalculateTotalAggregate<TSource>(afterFilterQueryable);
return result;
}
public virtual IQueryExecutionResult Execute(IQueryable queryable, IQueryCriteria criteria)
public IQueryExecutionResult<TSource> Execute<TSource>(IQueryable<TSource> queryable, IQueryCriteria criteria)
{
Reset(queryable, criteria);
return ExecuteReflected();
return FinalExecute<TSource, TSource>();
}
public IQueryExecutionResult<TRecord> Execute<TSource, TRecord>(IQueryable<TSource> queryable, IQueryCriteria criteria)
{
Reset(queryable, criteria);
return FinalExecute<TSource, TRecord>();
}
}
}
@@ -9,6 +9,7 @@ using PoweredSoft.DynamicQuery.Core;
namespace PoweredSoft.DynamicQuery
{
/*
public class QueryHandlerAsync : QueryHandlerBase, IQueryHandlerAsync
{
internal MethodInfo ExecuteAsyncGeneric = typeof(QueryHandlerAsync).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic).First(t => t.Name == "ExecuteAsync" && t.IsGenericMethod);
@@ -134,5 +135,5 @@ namespace PoweredSoft.DynamicQuery
var finalResult = whenAllResult.ToList();
return finalResult;
}
}
}*/
}
+81 -79
View File
@@ -31,11 +31,11 @@ namespace PoweredSoft.DynamicQuery
CurrentQueryable = QueryableAtStart;
}
protected virtual void CommonBeforeExecute<T>()
protected virtual void CommonBeforeExecute<TSource>()
{
ApplyIncludeStrategyInterceptors<T>();
ApplyBeforeFilterInterceptors<T>();
ApplyFilters<T>();
ApplyIncludeStrategyInterceptors<TSource>();
ApplyBeforeFilterInterceptors<TSource>();
ApplyFilters<TSource>();
}
public virtual void AddInterceptor(IQueryInterceptor interceptor)
@@ -46,7 +46,7 @@ namespace PoweredSoft.DynamicQuery
Interceptors.Add(interceptor);
}
protected virtual IGroup InterceptGroup<T>(IGroup group)
protected virtual IGroup InterceptGroup<TSource>(IGroup group)
{
var ret = Interceptors
.Where(t => t is IGroupInterceptor)
@@ -57,28 +57,28 @@ namespace PoweredSoft.DynamicQuery
}
protected virtual void ApplyPaging<T>()
protected virtual void ApplyPaging<TSource>()
{
if (!HasPaging)
return;
var q = (IQueryable<T>) CurrentQueryable;
var q = (IQueryable<TSource>) CurrentQueryable;
var skip = ((Criteria.Page ?? 1) - 1) * Criteria.PageSize.Value;
CurrentQueryable = q.Skip(skip).Take(Criteria.PageSize.Value);
}
protected virtual void ApplySorting<T>()
protected virtual void ApplySorting<TSource>()
{
if (Criteria.Sorts?.Any() != true)
{
ApplyNoSortInterceptor<T>();
ApplyNoSortInterceptor<TSource>();
return;
}
bool isAppending = false;
Criteria.Sorts.ForEach(sort =>
{
var transformedSort = InterceptSort<T>(sort);
var transformedSort = InterceptSort<TSource>(sort);
if (transformedSort.Count == 0)
return;
@@ -90,7 +90,7 @@ namespace PoweredSoft.DynamicQuery
});
}
protected DynamicClass FindMatchingAggregateResult(List<List<DynamicClass>> aggregateResults, List<IGroup> groups, List<IGroupQueryResult> groupResults)
protected DynamicClass FindMatchingAggregateResult<TRecord>(List<List<DynamicClass>> aggregateResults, List<IGroup> groups, List<IGroupQueryResult<TRecord>> groupResults)
{
var groupIndex = groupResults.Count - 1;
var aggregateLevel = aggregateResults[groupIndex];
@@ -108,7 +108,7 @@ namespace PoweredSoft.DynamicQuery
return ret;
}
protected virtual IQueryable CreateFetchAggregateSelectExpression<T>(IGroup finalGroup, List<IGroup> previousGroups)
protected virtual IQueryable CreateFetchAggregateSelectExpression<TSource>(IGroup finalGroup, List<IGroup> previousGroups)
{
var groupExpression = CurrentQueryable.GroupBy(QueryableUnderlyingType, gb =>
{
@@ -124,7 +124,7 @@ namespace PoweredSoft.DynamicQuery
sb.Key($"Key_{++groupKeyIndex}", $"Key_{groupKeyIndex}");
Criteria.Aggregates.ForEach((a, ai) =>
{
var fa = InterceptAggregate<T>(a);
var fa = InterceptAggregate<TSource>(a);
var selectType = ResolveSelectFrom(fa.Type);
sb.Aggregate(fa.Path, selectType, $"Agg_{ai}");
});
@@ -147,14 +147,14 @@ namespace PoweredSoft.DynamicQuery
return ret;
}
protected virtual IQueryable CreateTotalAggregateSelectExpression<T>(IQueryable queryableAfterFilters)
protected virtual IQueryable CreateTotalAggregateSelectExpression<TSource>(IQueryable queryableAfterFilters)
{
var groupExpression = queryableAfterFilters.EmptyGroupBy(QueryableUnderlyingType);
var selectExpression = groupExpression.Select(sb =>
{
Criteria.Aggregates.ForEach((a, index) =>
{
var fa = InterceptAggregate<T>(a);
var fa = InterceptAggregate<TSource>(a);
var selectType = ResolveSelectFrom(fa.Type);
sb.Aggregate(fa.Path, selectType, $"Agg_{index}");
});
@@ -162,7 +162,7 @@ namespace PoweredSoft.DynamicQuery
return selectExpression;
}
protected virtual void CalculatePageCount(IQueryExecutionResult result)
protected virtual void CalculatePageCount(IQueryExecutionResultPaging result)
{
if (!HasPaging)
return;
@@ -173,7 +173,7 @@ namespace PoweredSoft.DynamicQuery
result.NumberOfPages = result.TotalRecords / Criteria.PageSize + (result.TotalRecords % Criteria.PageSize != 0 ? 1 : 0);
}
protected virtual IAggregate InterceptAggregate<T>(IAggregate aggregate)
protected virtual IAggregate InterceptAggregate<TSource>(IAggregate aggregate)
{
var ret = Interceptors
.Where(t => t is IAggregateInterceptor)
@@ -182,47 +182,47 @@ namespace PoweredSoft.DynamicQuery
return ret;
}
protected virtual async Task<List<object>> InterceptConvertTo<T>(List<T> entities)
protected virtual async Task<List<TRecord>> InterceptConvertTo<TSource, TRecord>(List<TSource> entities)
{
await AfterEntityReadInterceptors(entities);
var objects = entities.Cast<object>().ToList();
for (var i = 0; i < objects.Count; i++)
objects[i] = InterceptConvertToObject<T>(objects[i]);
var ret = new List<TRecord>();
for (var i = 0; i < entities.Count; i++)
ret.Add(InterceptConvertToObject<TSource, TRecord>(entities[i]));
var pairs = entities.Select((t, index) => Tuple.Create(t, objects[index])).ToList();
await AfterReadInterceptors<T>(pairs);
var pairs = entities.Select((t, index) => Tuple.Create(t, (object)ret[index])).ToList();
await AfterReadInterceptors<TSource, TRecord>(pairs);
return objects;
return ret;
}
protected virtual async Task AfterEntityReadInterceptors<T>(List<T> entities)
protected virtual async Task AfterEntityReadInterceptors<TSource>(List<TSource> entities)
{
Interceptors
.Where(t => t is IAfterReadEntityInterceptor<T>)
.Cast<IAfterReadEntityInterceptor<T>>()
.Where(t => t is IAfterReadEntityInterceptor<TSource>)
.Cast<IAfterReadEntityInterceptor<TSource>>()
.ToList()
.ForEach(t => t.AfterReadEntity(entities));
var asyncInterceptors = Interceptors.Where(t => t is IAfterReadEntityInterceptorAsync<T>).Cast<IAfterReadEntityInterceptorAsync<T>>();
var asyncInterceptors = Interceptors.Where(t => t is IAfterReadEntityInterceptorAsync<TSource>).Cast<IAfterReadEntityInterceptorAsync<TSource>>();
foreach (var interceptor in asyncInterceptors)
await interceptor.AfterReadEntityAsync(entities);
}
protected virtual async Task AfterReadInterceptors<T>(List<Tuple<T, object>> pairs)
protected virtual async Task AfterReadInterceptors<TSource, TRecord>(List<Tuple<TSource, object>> pairs)
{
Interceptors
.Where(t => t is IAfterReadInterceptor<T>)
.Cast<IAfterReadInterceptor<T>>()
.Where(t => t is IAfterReadInterceptor<TSource>)
.Cast<IAfterReadInterceptor<TSource>>()
.ToList()
.ForEach(t => t.AfterRead(pairs));
var asyncInterceptors = Interceptors.Where(t => t is IAfterReadInterceptorAsync<T>).Cast<IAfterReadInterceptorAsync<T>>();
var asyncInterceptors = Interceptors.Where(t => t is IAfterReadInterceptorAsync<TSource>).Cast<IAfterReadInterceptorAsync<TSource>>();
foreach (var interceptor in asyncInterceptors)
await interceptor.AfterReadAsync(pairs);
}
protected virtual object InterceptConvertToObject<T>(object o)
protected virtual TRecord InterceptConvertToObject<TSource, TRecord>(object o)
{
o = Interceptors
.Where(t => t is IQueryConvertInterceptor)
@@ -230,20 +230,20 @@ namespace PoweredSoft.DynamicQuery
.Aggregate(o, (prev, interceptor) => interceptor.InterceptResultTo(prev));
o = Interceptors
.Where(t => t is IQueryConvertInterceptor<T>)
.Cast<IQueryConvertInterceptor<T>>()
.Where(t => t is IQueryConvertInterceptor<TSource>)
.Cast<IQueryConvertInterceptor<TSource>>()
.Aggregate(o, (prev, interceptor) =>
{
if (prev is T)
return interceptor.InterceptResultTo((T)prev);
if (prev is TSource)
return interceptor.InterceptResultTo((TSource)prev);
return o;
});
return o;
return (TRecord)o;
}
protected virtual List<ISort> InterceptSort<T>(ISort sort)
protected virtual List<ISort> InterceptSort<TSource>(ISort sort)
{
var original = new List<ISort>()
{
@@ -259,15 +259,15 @@ namespace PoweredSoft.DynamicQuery
return ret.ToList();
}
protected virtual void ApplyNoSortInterceptor<T>()
protected virtual void ApplyNoSortInterceptor<TSource>()
{
CurrentQueryable = Interceptors.Where(t => t is INoSortInterceptor)
.Cast<INoSortInterceptor>()
.Aggregate(CurrentQueryable, (prev, interceptor) => interceptor.InterceptNoSort(Criteria, prev));
CurrentQueryable = Interceptors.Where(t => t is INoSortInterceptor<T>)
.Cast<INoSortInterceptor<T>>()
.Aggregate((IQueryable<T>)CurrentQueryable, (prev, interceptor) => interceptor.InterceptNoSort(Criteria, prev));
CurrentQueryable = Interceptors.Where(t => t is INoSortInterceptor<TSource>)
.Cast<INoSortInterceptor<TSource>>()
.Aggregate((IQueryable<TSource>)CurrentQueryable, (prev, interceptor) => interceptor.InterceptNoSort(Criteria, prev));
}
@@ -292,40 +292,40 @@ namespace PoweredSoft.DynamicQuery
return ret.Value;
}
protected virtual void ApplyFilters<T>()
protected virtual void ApplyFilters<TSource>()
{
if (true != Criteria.Filters?.Any())
return;
CurrentQueryable = CurrentQueryable.Query(whereBuilder =>
{
Criteria.Filters.ForEach(filter => ApplyFilter<T>(whereBuilder, filter));
Criteria.Filters.ForEach(filter => ApplyFilter<TSource>(whereBuilder, filter));
});
}
protected virtual void ApplyFilter<T>(WhereBuilder whereBuilder, IFilter filter)
protected virtual void ApplyFilter<TSource>(WhereBuilder whereBuilder, IFilter filter)
{
var transformedFilter = InterceptFilter<T>(filter);
var transformedFilter = InterceptFilter<TSource>(filter);
if (transformedFilter is ISimpleFilter)
ApplySimpleFilter<T>(whereBuilder, transformedFilter as ISimpleFilter);
ApplySimpleFilter<TSource>(whereBuilder, transformedFilter as ISimpleFilter);
else if (transformedFilter is ICompositeFilter)
AppleCompositeFilter<T>(whereBuilder, transformedFilter as ICompositeFilter);
AppleCompositeFilter<TSource>(whereBuilder, transformedFilter as ICompositeFilter);
else
throw new NotSupportedException();
}
protected virtual void AppleCompositeFilter<T>(WhereBuilder whereBuilder, ICompositeFilter filter)
protected virtual void AppleCompositeFilter<TSource>(WhereBuilder whereBuilder, ICompositeFilter filter)
{
whereBuilder.SubQuery(subWhereBuilder => filter.Filters.ForEach(subFilter => ApplyFilter<T>(subWhereBuilder, subFilter)), filter.And == true);
whereBuilder.SubQuery(subWhereBuilder => filter.Filters.ForEach(subFilter => ApplyFilter<TSource>(subWhereBuilder, subFilter)), filter.And == true);
}
protected virtual void ApplySimpleFilter<T>(WhereBuilder whereBuilder, ISimpleFilter filter)
protected virtual void ApplySimpleFilter<TSource>(WhereBuilder whereBuilder, ISimpleFilter filter)
{
var resolvedConditionOperator = ResolveConditionOperatorFrom(filter.Type);
whereBuilder.Compare(filter.Path, resolvedConditionOperator, filter.Value, and: filter.And == true);
}
protected virtual IFilter InterceptFilter<T>(IFilter filter)
protected virtual IFilter InterceptFilter<TSource>(IFilter filter)
{
var ret = Interceptors.Where(t => t is IFilterInterceptor)
.Cast<IFilterInterceptor>()
@@ -334,7 +334,7 @@ namespace PoweredSoft.DynamicQuery
return ret;
}
protected virtual void ApplyIncludeStrategyInterceptors<T>()
protected virtual void ApplyIncludeStrategyInterceptors<TSource>()
{
CurrentQueryable = Interceptors
.Where(t => t is IIncludeStrategyInterceptor)
@@ -342,12 +342,12 @@ namespace PoweredSoft.DynamicQuery
.Aggregate(CurrentQueryable, (prev, interceptor) => interceptor.InterceptIncludeStrategy(Criteria, prev));
CurrentQueryable = Interceptors
.Where(t => t is IIncludeStrategyInterceptor<T>)
.Cast<IIncludeStrategyInterceptor<T>>()
.Aggregate((IQueryable<T>)CurrentQueryable, (prev, interceptor) => interceptor.InterceptIncludeStrategy(Criteria, prev));
.Where(t => t is IIncludeStrategyInterceptor<TSource>)
.Cast<IIncludeStrategyInterceptor<TSource>>()
.Aggregate((IQueryable<TSource>)CurrentQueryable, (prev, interceptor) => interceptor.InterceptIncludeStrategy(Criteria, prev));
}
protected virtual void ApplyBeforeFilterInterceptors<T>()
protected virtual void ApplyBeforeFilterInterceptors<TSource>()
{
CurrentQueryable = Interceptors
.Where(t => t is IBeforeQueryFilterInterceptor)
@@ -355,12 +355,12 @@ namespace PoweredSoft.DynamicQuery
.Aggregate(CurrentQueryable, (prev, interceptor) => interceptor.InterceptBeforeFiltering(Criteria, prev));
CurrentQueryable = Interceptors
.Where(t => t is IBeforeQueryFilterInterceptor<T>)
.Cast<IBeforeQueryFilterInterceptor<T>>()
.Aggregate((IQueryable<T>)CurrentQueryable, (prev, interceptor) => interceptor.InterceptBeforeFiltering(Criteria, prev));
.Where(t => t is IBeforeQueryFilterInterceptor<TSource>)
.Cast<IBeforeQueryFilterInterceptor<TSource>>()
.Aggregate((IQueryable<TSource>)CurrentQueryable, (prev, interceptor) => interceptor.InterceptBeforeFiltering(Criteria, prev));
}
protected virtual List<object> RecursiveRegroup<T>(List<DynamicClass> groupRecords, List<List<DynamicClass>> aggregateResults, IGroup group, List<List<object>> lastLists, List<IGroupQueryResult> parentGroupResults = null)
protected virtual List<IGroupQueryResult<TRecord>> RecursiveRegroup<TSource, TRecord>(List<DynamicClass> groupRecords, List<List<DynamicClass>> aggregateResults, IGroup group, List<(List<TSource> entities, IGroupQueryResult<TRecord> group)> lastLists, List<IGroupQueryResult<TRecord>> parentGroupResults = null)
{
var groupIndex = Criteria.Groups.IndexOf(group);
var isLast = Criteria.Groups.Last() == group;
@@ -371,13 +371,13 @@ namespace PoweredSoft.DynamicQuery
.GroupBy(gk => gk.GetDynamicPropertyValue($"Key_{groupIndex}"))
.Select(t =>
{
var groupResult = new GroupQueryResult();
var groupResult = new GroupQueryResult<TRecord>();
// group results.
List<IGroupQueryResult> groupResults;
List<IGroupQueryResult<TRecord>> groupResults;
if (parentGroupResults == null)
groupResults = new List<IGroupQueryResult> { groupResult };
groupResults = new List<IGroupQueryResult<TRecord>> { groupResult };
else
groupResults = parentGroupResults.Union(new[] { groupResult }).ToList();
@@ -406,41 +406,43 @@ namespace PoweredSoft.DynamicQuery
if (isLast)
{
var entities = t.SelectMany(t2 => t2.GetDynamicPropertyValue<List<T>>("Records")).ToList();
groupResult.Data = entities.Cast<object>().ToList();
lastLists.Add(groupResult.Data);
var entities = t.SelectMany(t2 => t2.GetDynamicPropertyValue<List<TSource>>("Records")).ToList();
var tuple = (entities, groupResult);
groupResult.Data = new List<TRecord>();
lastLists.Add(tuple);
}
else
{
groupResult.Data = RecursiveRegroup<T>(t.ToList(), aggregateResults, Criteria.Groups[groupIndex + 1], lastLists, groupResults);
groupResult.SubGroups = RecursiveRegroup<TSource, TRecord>(t.ToList(), aggregateResults, Criteria.Groups[groupIndex + 1], lastLists, groupResults);
}
return groupResult;
})
.AsEnumerable<object>()
.AsEnumerable<IGroupQueryResult<TRecord>>()
.ToList();
return ret;
}
protected virtual async Task QueryInterceptToGrouped<T>(List<List<object>> lists)
protected virtual async Task QueryInterceptToGrouped<TSource, TRecord>(List<(List<TSource> entities, IGroupQueryResult<TRecord> group)> lists)
{
var entities = lists.SelectMany(t => t).Cast<T>().ToList();
var entities = lists.SelectMany(t => t.entities).ToList();
await AfterEntityReadInterceptors(entities);
var pairs = new List<Tuple<T, object>>();
var pairs = new List<Tuple<TSource, object>>();
lists.ForEach(innerList =>
{
for(var i = 0; i < innerList.Count; i++)
for (var i = 0; i < innerList.entities.Count; i++)
{
var entity = (T)innerList[i];
var convertedObject = InterceptConvertToObject<T>(entity);
innerList[i] = convertedObject;
pairs.Add(Tuple.Create(entity, convertedObject));
var entity = innerList.entities[i];
var convertedObject = InterceptConvertToObject<TSource, TRecord>(entity);
innerList.group.Data.Add(convertedObject);
pairs.Add(Tuple.Create(entity, convertedObject as object));
}
});
await AfterReadInterceptors<T>(pairs);
await AfterReadInterceptors<TSource, TRecord>(pairs);
}
}
}
+11 -4
View File
@@ -19,25 +19,32 @@ namespace PoweredSoft.DynamicQuery
}
// part of a result.
public abstract class QueryResult : IQueryResult
public abstract class QueryResult<TRecord> : IQueryResult<TRecord>
{
public List<IAggregateResult> Aggregates { get; set; }
public List<object> Data { get; set; }
public List<TRecord> Data { get; set; }
public bool ShouldSerializeAggregates() => Aggregates != null;
}
// just result
public class QueryExecutionResult : QueryResult, IQueryExecutionResult
public class QueryExecutionResult<TRecord> : QueryResult<TRecord>, IQueryExecutionResult<TRecord>
{
public long TotalRecords { get; set; }
public long? NumberOfPages { get; set; }
}
public class QueryGroupExecutionResult<TRecord> : QueryExecutionResult<TRecord>, IQueryExecutionGroupResult<TRecord>
{
public List<IGroupQueryResult<TRecord>> Groups { get; set; }
}
// group result.
public class GroupQueryResult : QueryResult, IGroupQueryResult
public class GroupQueryResult<TRecord> : QueryResult<TRecord>, IGroupQueryResult<TRecord>
{
public string GroupPath { get; set; }
public object GroupValue { get; set; }
public bool HasSubGroups { get; set; }
public List<IGroupQueryResult<TRecord>> SubGroups { get; set; }
}
}
@@ -18,7 +18,7 @@ namespace PoweredSoft.DynamicQuery
services.TryAddTransient<IGroup, Group>();
services.TryAddTransient<IQueryCriteria, QueryCriteria>();
services.TryAddTransient<IQueryHandler, QueryHandler>();
services.TryAddTransient<IQueryHandlerAsync, QueryHandlerAsync>();
//services.TryAddTransient<IQueryHandlerAsync, QueryHandlerAsync>();
return services;
}
}