ready for version 2

This commit is contained in:
David Lebee
2019-03-22 15:27:04 -05:00
parent 9e6dc08e53
commit dc9c7e1674
8 changed files with 174 additions and 171 deletions
@@ -8,7 +8,7 @@
<RepositoryUrl>https://github.com/PoweredSoft/DynamicQuery</RepositoryUrl>
<RepositoryType>github</RepositoryType>
<PackageTags>powered,soft,dynamic,criteria,query,builder</PackageTags>
<Version>1.0.0$(VersionSuffix)</Version>
<Version>2.0.0$(VersionSuffix)</Version>
<PackageIconUrl>https://secure.gravatar.com/avatar/4e32f73820c16718909a06c2927f1f8b?s=512&amp;amp;r=g&amp;amp;d=retro</PackageIconUrl>
<Product>PoweredSoft.DynamicQuery</Product>
<Description>dynamic query based on string path very usefull for network requests.</Description>
+1 -1
View File
@@ -22,7 +22,7 @@ namespace PoweredSoft.DynamicQuery
protected virtual IQueryExecutionResult<TRecord> ExecuteGrouping<TSource, TRecord>()
{
var result = new QueryGroupExecutionResult<TRecord>();
var result = new QueryExecutionGroupResult<TRecord>();
// preserve queryable.
var queryableAfterFilters = CurrentQueryable;
+41 -38
View File
@@ -3,61 +3,52 @@ using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using PoweredSoft.Data;
using PoweredSoft.Data.Core;
using PoweredSoft.DynamicLinq;
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);
public IAsyncQueryableService AsyncQueryableService { get; }
internal Task<IQueryExecutionResult> ExecuteAsyncReflected(CancellationToken cancellationToken) => (Task<IQueryExecutionResult>)ExecuteAsyncGeneric.MakeGenericMethod(QueryableUnderlyingType).Invoke(this, new object[] { cancellationToken });
public QueryHandlerAsync(IAsyncQueryableService asyncQueryableService)
{
AsyncQueryableService = asyncQueryableService;
}
protected virtual Task<IQueryExecutionResult> ExecuteAsync<T>(CancellationToken cancellationToken = default(CancellationToken))
protected virtual Task<IQueryExecutionResult<TRecord>> FinalExecuteAsync<TSource, TRecord>(CancellationToken cancellationToken = default(CancellationToken))
{
CommonBeforeExecute<T>();
return HasGrouping ? ExecuteAsyncGrouping<T>(cancellationToken) : ExecuteAsyncNoGrouping<T>(cancellationToken);
CommonBeforeExecute<TSource>();
return HasGrouping ? ExecuteAsyncGrouping<TSource, TRecord>(cancellationToken) : ExecuteAsyncNoGrouping<TSource, TRecord>(cancellationToken);
}
public Task<IQueryExecutionResult> ExecuteAsync(IQueryable queryable, IQueryCriteria criteria, CancellationToken cancellationToken = default(CancellationToken))
protected virtual async Task<IQueryExecutionResult<TRecord>> ExecuteAsyncGrouping<TSource, TRecord>(CancellationToken cancellationToken)
{
Reset(queryable, criteria);
return ExecuteAsyncReflected(cancellationToken);
}
protected virtual async Task<IQueryExecutionResult> ExecuteAsyncGrouping<T>(CancellationToken cancellationToken)
{
var result = new QueryExecutionResult();
var result = new QueryExecutionGroupResult<TRecord>();
// preserve queryable.
var queryableAfterFilters = CurrentQueryable;
// async.
result.TotalRecords = await this.AsyncQueryableService.LongCountAsync((IQueryable<T>)queryableAfterFilters, cancellationToken);
result.TotalRecords = await this.AsyncQueryableService.LongCountAsync((IQueryable<TSource>)queryableAfterFilters, cancellationToken);
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 = await FetchAggregatesAsync<T>(finalGroups, cancellationToken);
var aggregateResults = await FetchAggregatesAsync<TSource>(finalGroups, cancellationToken);
// 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}")));
@@ -71,52 +62,52 @@ namespace PoweredSoft.DynamicQuery
var groupRecords = await AsyncQueryableService.ToListAsync(CurrentQueryable.Cast<DynamicClass>(), cancellationToken);
// 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> entities, IGroupQueryResult<TRecord> group)>();
result.Groups = RecursiveRegroup<TSource, TRecord>(groupRecords, aggregateResults, Criteria.Groups.First(), lastLists);
// converted to grouped by.
await QueryInterceptToGrouped<T>(lastLists);
await QueryInterceptToGrouped<TSource, TRecord>(lastLists);
result.Aggregates = await CalculateTotalAggregateAsync<T>(queryableAfterFilters, cancellationToken);
result.Aggregates = await CalculateTotalAggregateAsync<TSource>(queryableAfterFilters, cancellationToken);
return result;
}
protected async Task<IQueryExecutionResult> ExecuteAsyncNoGrouping<T>(CancellationToken cancellationToken)
protected async Task<IQueryExecutionResult<TRecord>> ExecuteAsyncNoGrouping<TSource, TRecord>(CancellationToken cancellationToken)
{
var result = new QueryExecutionResult();
var result = new QueryExecutionResult<TRecord>();
// after filter queryable
IQueryable<T> afterFilterQueryable = (IQueryable<T>)CurrentQueryable;
IQueryable<TSource> afterFilterQueryable = (IQueryable<TSource>)CurrentQueryable;
// total records.
result.TotalRecords = await AsyncQueryableService.LongCountAsync(afterFilterQueryable, cancellationToken);
CalculatePageCount(result);
// sorts and paging.
ApplySorting<T>();
ApplyPaging<T>();
ApplySorting<TSource>();
ApplyPaging<TSource>();
// data.
var entities = await AsyncQueryableService.ToListAsync(((IQueryable<T>)CurrentQueryable), cancellationToken);
var records = await InterceptConvertTo<T>(entities);
var entities = await AsyncQueryableService.ToListAsync(((IQueryable<TSource>)CurrentQueryable), cancellationToken);
var records = await InterceptConvertTo<TSource, TRecord>(entities);
result.Data = records;
// aggregates.
result.Aggregates = await CalculateTotalAggregateAsync<T>(afterFilterQueryable, cancellationToken);
result.Aggregates = await CalculateTotalAggregateAsync<TSource>(afterFilterQueryable, cancellationToken);
return result;
}
protected virtual async Task<List<IAggregateResult>> CalculateTotalAggregateAsync<T>(IQueryable queryableAfterFilters, CancellationToken cancellationToken)
protected virtual async Task<List<IAggregateResult>> CalculateTotalAggregateAsync<TSource>(IQueryable queryableAfterFilters, CancellationToken cancellationToken)
{
if (!Criteria.Aggregates.Any())
return null;
IQueryable selectExpression = CreateTotalAggregateSelectExpression<T>(queryableAfterFilters);
IQueryable selectExpression = CreateTotalAggregateSelectExpression<TSource>(queryableAfterFilters);
var aggregateResult = await AsyncQueryableService.FirstOrDefaultAsync(selectExpression.Cast<DynamicClass>());
return MaterializeCalculateTotalAggregateResult(aggregateResult);
}
protected async virtual Task<List<List<DynamicClass>>> FetchAggregatesAsync<T>(List<IGroup> finalGroups, CancellationToken cancellationToken)
protected async virtual Task<List<List<DynamicClass>>> FetchAggregatesAsync<TSource>(List<IGroup> finalGroups, CancellationToken cancellationToken)
{
if (!Criteria.Aggregates.Any())
return null;
@@ -125,7 +116,7 @@ namespace PoweredSoft.DynamicQuery
var whenAllResult = await Task.WhenAll(finalGroups.Select(fg =>
{
IQueryable selectExpression = CreateFetchAggregateSelectExpression<T>(fg, previousGroups);
IQueryable selectExpression = CreateFetchAggregateSelectExpression<TSource>(fg, previousGroups);
var selectExpressionCasted = selectExpression.Cast<DynamicClass>();
var aggregateResult = AsyncQueryableService.ToListAsync(selectExpressionCasted, cancellationToken);
previousGroups.Add(fg);
@@ -135,5 +126,17 @@ namespace PoweredSoft.DynamicQuery
var finalResult = whenAllResult.ToList();
return finalResult;
}
}*/
public Task<IQueryExecutionResult<TSource>> ExecuteAsync<TSource>(IQueryable<TSource> queryable, IQueryCriteria criteria, CancellationToken cancellationToken = default(CancellationToken))
{
Reset(queryable, criteria);
return FinalExecuteAsync<TSource, TSource>(cancellationToken);
}
public Task<IQueryExecutionResult<TRecord>> ExecuteAsync<TSource, TRecord>(IQueryable<TSource> queryable, IQueryCriteria criteria, CancellationToken cancellationToken = default(CancellationToken))
{
Reset(queryable, criteria);
return FinalExecuteAsync<TSource, TRecord>(cancellationToken);
}
}
}
+1 -1
View File
@@ -34,7 +34,7 @@ namespace PoweredSoft.DynamicQuery
public long? NumberOfPages { get; set; }
}
public class QueryGroupExecutionResult<TRecord> : QueryExecutionResult<TRecord>, IQueryExecutionGroupResult<TRecord>
public class QueryExecutionGroupResult<TRecord> : QueryExecutionResult<TRecord>, IQueryExecutionGroupResult<TRecord>
{
public List<IGroupQueryResult<TRecord>> Groups { get; set; }
}