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

View File

@ -8,7 +8,7 @@
<RepositoryUrl>https://github.com/PoweredSoft/DynamicQuery</RepositoryUrl> <RepositoryUrl>https://github.com/PoweredSoft/DynamicQuery</RepositoryUrl>
<RepositoryType>github</RepositoryType> <RepositoryType>github</RepositoryType>
<PackageTags>powered,soft,dynamic,criteria,query,builder,asp,net,core</PackageTags> <PackageTags>powered,soft,dynamic,criteria,query,builder,asp,net,core</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> <PackageIconUrl>https://secure.gravatar.com/avatar/4e32f73820c16718909a06c2927f1f8b?s=512&amp;amp;r=g&amp;amp;d=retro</PackageIconUrl>
<Product>PoweredSoft.DynamicQuery.AspNetCore</Product> <Product>PoweredSoft.DynamicQuery.AspNetCore</Product>
<Description>This projects makes it easier to use dynamic query in a asp.net core mvc project.</Description> <Description>This projects makes it easier to use dynamic query in a asp.net core mvc project.</Description>

View File

@ -19,7 +19,6 @@ namespace PoweredSoft.DynamicQuery.Core
public interface IQueryHandlerAsync : IInterceptableQueryHandler public interface IQueryHandlerAsync : IInterceptableQueryHandler
{ {
Task<IQueryExecutionResult<object>> ExecuteAsync(IQueryable queryable, IQueryCriteria criteria, CancellationToken cancellationToken = default(CancellationToken));
Task<IQueryExecutionResult<TSource>> ExecuteAsync<TSource>(IQueryable<TSource> queryable, IQueryCriteria criteria, CancellationToken cancellationToken = default(CancellationToken)); Task<IQueryExecutionResult<TSource>> ExecuteAsync<TSource>(IQueryable<TSource> queryable, IQueryCriteria criteria, CancellationToken cancellationToken = default(CancellationToken));
Task<IQueryExecutionResult<TRecord>> ExecuteAsync<TSource, TRecord>(IQueryable<TSource> queryable, IQueryCriteria criteria, CancellationToken cancellationToken = default(CancellationToken)); Task<IQueryExecutionResult<TRecord>> ExecuteAsync<TSource, TRecord>(IQueryable<TSource> queryable, IQueryCriteria criteria, CancellationToken cancellationToken = default(CancellationToken));
} }

View File

@ -8,7 +8,7 @@
<RepositoryUrl>https://github.com/PoweredSoft/DynamicQuery.Core/</RepositoryUrl> <RepositoryUrl>https://github.com/PoweredSoft/DynamicQuery.Core/</RepositoryUrl>
<RepositoryType>github</RepositoryType> <RepositoryType>github</RepositoryType>
<PackageTags>powered,soft,dynamic,criteria,query,builder</PackageTags> <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> <PackageIconUrl>https://secure.gravatar.com/avatar/4e32f73820c16718909a06c2927f1f8b?s=512&amp;amp;r=g&amp;amp;d=retro</PackageIconUrl>
<Product>PoweredSoft.DynamicQuery.Core</Product> <Product>PoweredSoft.DynamicQuery.Core</Product>
<Description>core abstractions</Description> <Description>core abstractions</Description>

View File

@ -1,141 +1,142 @@
//using PoweredSoft.Data; using PoweredSoft.Data;
//using PoweredSoft.Data.EntityFrameworkCore; using PoweredSoft.Data.EntityFrameworkCore;
//using PoweredSoft.DynamicQuery.Core; using PoweredSoft.DynamicQuery.Core;
//using PoweredSoft.DynamicQuery.Test.Mock; using PoweredSoft.DynamicQuery.Extensions;
//using System; using PoweredSoft.DynamicQuery.Test.Mock;
//using System.Collections.Generic; using System;
//using System.Linq; using System.Collections.Generic;
//using System.Text; using System.Linq;
//using System.Threading.Tasks; using System.Text;
//using Xunit; using System.Threading.Tasks;
using Xunit;
//namespace PoweredSoft.DynamicQuery.Test namespace PoweredSoft.DynamicQuery.Test
//{ {
// public class AsyncTests public class AsyncTests
// { {
// [Fact] [Fact]
// public void TestEmptyCriteria() public void TestEmptyCriteria()
// { {
// MockContextFactory.SeedAndTestContextFor("AsyncTests_TestEmptyCriteria", TestSeeders.SimpleSeedScenario, async ctx => MockContextFactory.SeedAndTestContextFor("AsyncTests_TestEmptyCriteria", TestSeeders.SimpleSeedScenario, async ctx =>
// { {
// var resultShouldMatch = ctx.Items.ToList(); var resultShouldMatch = ctx.Items.ToList();
// var queryable = ctx.Items.AsQueryable(); var queryable = ctx.Items.AsQueryable();
// // query handler that is empty should be the same as running to list. // query handler that is empty should be the same as running to list.
// var aqf = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() }); var aqf = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() });
// var criteria = new QueryCriteria(); var criteria = new QueryCriteria();
// var queryHandler = new QueryHandlerAsync(aqf); var queryHandler = new QueryHandlerAsync(aqf);
// var result = await queryHandler.ExecuteAsync(queryable, criteria); var result = await queryHandler.ExecuteAsync(queryable, criteria);
// Assert.Equal(resultShouldMatch, result.Data); Assert.Equal(resultShouldMatch, result.Data);
// }); });
// } }
// [Fact] [Fact]
// public void WithGrouping() public void WithGrouping()
// { {
// MockContextFactory.SeedAndTestContextFor("AsyncTests_WithGrouping", TestSeeders.SimpleSeedScenario, async ctx => MockContextFactory.SeedAndTestContextFor("AsyncTests_WithGrouping", TestSeeders.SimpleSeedScenario, async ctx =>
// { {
// var shouldResults = ctx.OrderItems var shouldResults = ctx.OrderItems
// .GroupBy(t => t.Order.CustomerId) .GroupBy(t => t.Order.CustomerId)
// .Select(t => new .Select(t => new
// { {
// GroupValue = t.Key, GroupValue = t.Key,
// Count = t.Count(), Count = t.Count(),
// ItemQuantityAverage = t.Average(t2 => t2.Quantity), ItemQuantityAverage = t.Average(t2 => t2.Quantity),
// ItemQuantitySum = t.Sum(t2 => t2.Quantity), ItemQuantitySum = t.Sum(t2 => t2.Quantity),
// AvgOfPrice = t.Average(t2 => t2.PriceAtTheTime) AvgOfPrice = t.Average(t2 => t2.PriceAtTheTime)
// }) })
// .ToList(); .ToList();
// // query handler that is empty should be the same as running to list. // query handler that is empty should be the same as running to list.
// var criteria = new QueryCriteria() var criteria = new QueryCriteria()
// { {
// Groups = new List<IGroup> Groups = new List<IGroup>
// { {
// new Group { Path = "Order.CustomerId" } new Group { Path = "Order.CustomerId" }
// }, },
// Aggregates = new List<Core.IAggregate> Aggregates = new List<Core.IAggregate>
// { {
// new Aggregate { Type = AggregateType.Count }, new Aggregate { Type = AggregateType.Count },
// new Aggregate { Type = AggregateType.Avg, Path = "Quantity" }, new Aggregate { Type = AggregateType.Avg, Path = "Quantity" },
// new Aggregate { Type = AggregateType.Sum, Path = "Quantity" }, new Aggregate { Type = AggregateType.Sum, Path = "Quantity" },
// new Aggregate { Type = AggregateType.Avg, Path = "PriceAtTheTime"} new Aggregate { Type = AggregateType.Avg, Path = "PriceAtTheTime"}
// } }
// }; };
// var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() }); var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() });
// var queryHandler = new QueryHandlerAsync(asyncService); var queryHandler = new QueryHandlerAsync(asyncService);
// var result = await queryHandler.ExecuteAsync(ctx.OrderItems, criteria); var result = await queryHandler.ExecuteAsync(ctx.OrderItems, criteria);
// var groups = result.Data.Cast<IGroupQueryResult>().ToList(); var groups = result.GroupedResult().Groups;
// // validate group and aggregates of groups. // validate group and aggregates of groups.
// Assert.Equal(groups.Count, shouldResults.Count); Assert.Equal(groups.Count, shouldResults.Count);
// Assert.All(groups, g => Assert.All(groups, g =>
// { {
// var index = groups.IndexOf(g); var index = groups.IndexOf(g);
// var shouldResult = shouldResults[index]; var shouldResult = shouldResults[index];
// // validate the group value. // validate the group value.
// Assert.Equal(g.GroupValue, shouldResult.GroupValue); Assert.Equal(g.GroupValue, shouldResult.GroupValue);
// // validate the group aggregates. // validate the group aggregates.
// var aggCount = g.Aggregates.First(t => t.Type == AggregateType.Count); var aggCount = g.Aggregates.First(t => t.Type == AggregateType.Count);
// var aggItemQuantityAverage = g.Aggregates.First(t => t.Type == AggregateType.Avg && t.Path == "Quantity"); var aggItemQuantityAverage = g.Aggregates.First(t => t.Type == AggregateType.Avg && t.Path == "Quantity");
// var aggItemQuantitySum = g.Aggregates.First(t => t.Type == AggregateType.Sum && t.Path == "Quantity"); var aggItemQuantitySum = g.Aggregates.First(t => t.Type == AggregateType.Sum && t.Path == "Quantity");
// var aggAvgOfPrice = g.Aggregates.First(t => t.Type == AggregateType.Avg && t.Path == "PriceAtTheTime"); var aggAvgOfPrice = g.Aggregates.First(t => t.Type == AggregateType.Avg && t.Path == "PriceAtTheTime");
// Assert.Equal(shouldResult.Count, aggCount.Value); Assert.Equal(shouldResult.Count, aggCount.Value);
// Assert.Equal(shouldResult.ItemQuantityAverage, aggItemQuantityAverage.Value); Assert.Equal(shouldResult.ItemQuantityAverage, aggItemQuantityAverage.Value);
// Assert.Equal(shouldResult.ItemQuantitySum, aggItemQuantitySum.Value); Assert.Equal(shouldResult.ItemQuantitySum, aggItemQuantitySum.Value);
// Assert.Equal(shouldResult.AvgOfPrice, aggAvgOfPrice.Value); Assert.Equal(shouldResult.AvgOfPrice, aggAvgOfPrice.Value);
// }); });
// }); });
// } }
// [Fact] [Fact]
// public void SimpleFilter() public void SimpleFilter()
// { {
// MockContextFactory.SeedAndTestContextFor("AsyncTests_SimpleFilter", TestSeeders.SimpleSeedScenario, async ctx => MockContextFactory.SeedAndTestContextFor("AsyncTests_SimpleFilter", TestSeeders.SimpleSeedScenario, async ctx =>
// { {
// var resultShouldMatch = ctx.Items.Where(t => t.Name.EndsWith("Cables")).ToList(); var resultShouldMatch = ctx.Items.Where(t => t.Name.EndsWith("Cables")).ToList();
// var criteria = new QueryCriteria() var criteria = new QueryCriteria()
// { {
// Filters = new List<IFilter> Filters = new List<IFilter>
// { {
// new SimpleFilter new SimpleFilter
// { {
// Path = "Name", Path = "Name",
// Type = FilterType.EndsWith, Type = FilterType.EndsWith,
// Value = "Cables" Value = "Cables"
// } }
// } }
// }; };
// var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() }); var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() });
// var queryHandler = new QueryHandlerAsync(asyncService); var queryHandler = new QueryHandlerAsync(asyncService);
// var result = await queryHandler.ExecuteAsync(ctx.Items, criteria); var result = await queryHandler.ExecuteAsync(ctx.Items, criteria);
// Assert.Equal(resultShouldMatch, result.Data); Assert.Equal(resultShouldMatch, result.Data);
// }); });
// } }
// [Fact] [Fact]
// public void TestPaging() public void TestPaging()
// { {
// MockContextFactory.SeedAndTestContextFor("AsyncTests_TestPagging", TestSeeders.SimpleSeedScenario, async ctx => MockContextFactory.SeedAndTestContextFor("AsyncTests_TestPagging", TestSeeders.SimpleSeedScenario, async ctx =>
// { {
// var resultShouldMatch = ctx.OrderItems.OrderBy(t => t.Id).Skip(5).Take(5).ToList(); var resultShouldMatch = ctx.OrderItems.OrderBy(t => t.Id).Skip(5).Take(5).ToList();
// // query handler that is empty should be the same as running to list. // query handler that is empty should be the same as running to list.
// var criteria = new QueryCriteria(); var criteria = new QueryCriteria();
// criteria.Sorts.Add(new Sort("Id")); criteria.Sorts.Add(new Sort("Id"));
// criteria.Page = 2; criteria.Page = 2;
// criteria.PageSize = 5; criteria.PageSize = 5;
// var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() }); var asyncService = new AsyncQueryableService(new[] { new AsyncQueryableHandlerService() });
// var queryHandler = new QueryHandlerAsync(asyncService); var queryHandler = new QueryHandlerAsync(asyncService);
// var result = await queryHandler.ExecuteAsync(ctx.OrderItems, criteria); var result = await queryHandler.ExecuteAsync(ctx.OrderItems, criteria);
// Assert.Equal(resultShouldMatch, result.Data); Assert.Equal(resultShouldMatch, result.Data);
// }); });
// } }
// } }
//} }

View File

@ -8,7 +8,7 @@
<RepositoryUrl>https://github.com/PoweredSoft/DynamicQuery</RepositoryUrl> <RepositoryUrl>https://github.com/PoweredSoft/DynamicQuery</RepositoryUrl>
<RepositoryType>github</RepositoryType> <RepositoryType>github</RepositoryType>
<PackageTags>powered,soft,dynamic,criteria,query,builder</PackageTags> <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> <PackageIconUrl>https://secure.gravatar.com/avatar/4e32f73820c16718909a06c2927f1f8b?s=512&amp;amp;r=g&amp;amp;d=retro</PackageIconUrl>
<Product>PoweredSoft.DynamicQuery</Product> <Product>PoweredSoft.DynamicQuery</Product>
<Description>dynamic query based on string path very usefull for network requests.</Description> <Description>dynamic query based on string path very usefull for network requests.</Description>

View File

@ -22,7 +22,7 @@ namespace PoweredSoft.DynamicQuery
protected virtual IQueryExecutionResult<TRecord> ExecuteGrouping<TSource, TRecord>() protected virtual IQueryExecutionResult<TRecord> ExecuteGrouping<TSource, TRecord>()
{ {
var result = new QueryGroupExecutionResult<TRecord>(); var result = new QueryExecutionGroupResult<TRecord>();
// preserve queryable. // preserve queryable.
var queryableAfterFilters = CurrentQueryable; var queryableAfterFilters = CurrentQueryable;

View File

@ -3,61 +3,52 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using PoweredSoft.Data;
using PoweredSoft.Data.Core; using PoweredSoft.Data.Core;
using PoweredSoft.DynamicLinq; using PoweredSoft.DynamicLinq;
using PoweredSoft.DynamicQuery.Core; using PoweredSoft.DynamicQuery.Core;
namespace PoweredSoft.DynamicQuery namespace PoweredSoft.DynamicQuery
{ {
/*
public class QueryHandlerAsync : QueryHandlerBase, IQueryHandlerAsync 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; } public IAsyncQueryableService AsyncQueryableService { get; }
internal Task<IQueryExecutionResult> ExecuteAsyncReflected(CancellationToken cancellationToken) => (Task<IQueryExecutionResult>)ExecuteAsyncGeneric.MakeGenericMethod(QueryableUnderlyingType).Invoke(this, new object[] { cancellationToken });
public QueryHandlerAsync(IAsyncQueryableService asyncQueryableService) public QueryHandlerAsync(IAsyncQueryableService asyncQueryableService)
{ {
AsyncQueryableService = 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>(); CommonBeforeExecute<TSource>();
return HasGrouping ? ExecuteAsyncGrouping<T>(cancellationToken) : ExecuteAsyncNoGrouping<T>(cancellationToken); 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); var result = new QueryExecutionGroupResult<TRecord>();
return ExecuteAsyncReflected(cancellationToken);
}
protected virtual async Task<IQueryExecutionResult> ExecuteAsyncGrouping<T>(CancellationToken cancellationToken)
{
var result = new QueryExecutionResult();
// preserve queryable. // preserve queryable.
var queryableAfterFilters = CurrentQueryable; var queryableAfterFilters = CurrentQueryable;
// async. // async.
result.TotalRecords = await this.AsyncQueryableService.LongCountAsync((IQueryable<T>)queryableAfterFilters, cancellationToken); result.TotalRecords = await this.AsyncQueryableService.LongCountAsync((IQueryable<TSource>)queryableAfterFilters, cancellationToken);
CalculatePageCount(result); CalculatePageCount(result);
// intercept groups in advance to avoid doing it more than once :) // 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. // get the aggregates.
var aggregateResults = await FetchAggregatesAsync<T>(finalGroups, cancellationToken); var aggregateResults = await FetchAggregatesAsync<TSource>(finalGroups, cancellationToken);
// sorting. // sorting.
finalGroups.ForEach(fg => Criteria.Sorts.Insert(0, new Sort(fg.Path, fg.Ascending))); finalGroups.ForEach(fg => Criteria.Sorts.Insert(0, new Sort(fg.Path, fg.Ascending)));
// apply sorting and paging. // apply sorting and paging.
ApplySorting<T>(); ApplySorting<TSource>();
ApplyPaging<T>(); ApplyPaging<TSource>();
// create group & select expression. // create group & select expression.
CurrentQueryable = CurrentQueryable.GroupBy(QueryableUnderlyingType, gb => finalGroups.ForEach((fg, index) => gb.Path(fg.Path, $"Key_{index}"))); 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); var groupRecords = await AsyncQueryableService.ToListAsync(CurrentQueryable.Cast<DynamicClass>(), cancellationToken);
// now join them into logical collections // now join them into logical collections
var lastLists = new List<List<object>>(); var lastLists = new List<(List<TSource> entities, IGroupQueryResult<TRecord> group)>();
result.Data = RecursiveRegroup<T>(groupRecords, aggregateResults, Criteria.Groups.First(), lastLists); result.Groups = RecursiveRegroup<TSource, TRecord>(groupRecords, aggregateResults, Criteria.Groups.First(), lastLists);
// converted to grouped by. // 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; 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 // after filter queryable
IQueryable<T> afterFilterQueryable = (IQueryable<T>)CurrentQueryable; IQueryable<TSource> afterFilterQueryable = (IQueryable<TSource>)CurrentQueryable;
// total records. // total records.
result.TotalRecords = await AsyncQueryableService.LongCountAsync(afterFilterQueryable, cancellationToken); result.TotalRecords = await AsyncQueryableService.LongCountAsync(afterFilterQueryable, cancellationToken);
CalculatePageCount(result); CalculatePageCount(result);
// sorts and paging. // sorts and paging.
ApplySorting<T>(); ApplySorting<TSource>();
ApplyPaging<T>(); ApplyPaging<TSource>();
// data. // data.
var entities = await AsyncQueryableService.ToListAsync(((IQueryable<T>)CurrentQueryable), cancellationToken); var entities = await AsyncQueryableService.ToListAsync(((IQueryable<TSource>)CurrentQueryable), cancellationToken);
var records = await InterceptConvertTo<T>(entities); var records = await InterceptConvertTo<TSource, TRecord>(entities);
result.Data = records; result.Data = records;
// aggregates. // aggregates.
result.Aggregates = await CalculateTotalAggregateAsync<T>(afterFilterQueryable, cancellationToken); result.Aggregates = await CalculateTotalAggregateAsync<TSource>(afterFilterQueryable, cancellationToken);
return result; 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()) if (!Criteria.Aggregates.Any())
return null; return null;
IQueryable selectExpression = CreateTotalAggregateSelectExpression<T>(queryableAfterFilters); IQueryable selectExpression = CreateTotalAggregateSelectExpression<TSource>(queryableAfterFilters);
var aggregateResult = await AsyncQueryableService.FirstOrDefaultAsync(selectExpression.Cast<DynamicClass>()); var aggregateResult = await AsyncQueryableService.FirstOrDefaultAsync(selectExpression.Cast<DynamicClass>());
return MaterializeCalculateTotalAggregateResult(aggregateResult); 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()) if (!Criteria.Aggregates.Any())
return null; return null;
@ -125,7 +116,7 @@ namespace PoweredSoft.DynamicQuery
var whenAllResult = await Task.WhenAll(finalGroups.Select(fg => 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 selectExpressionCasted = selectExpression.Cast<DynamicClass>();
var aggregateResult = AsyncQueryableService.ToListAsync(selectExpressionCasted, cancellationToken); var aggregateResult = AsyncQueryableService.ToListAsync(selectExpressionCasted, cancellationToken);
previousGroups.Add(fg); previousGroups.Add(fg);
@ -135,5 +126,17 @@ namespace PoweredSoft.DynamicQuery
var finalResult = whenAllResult.ToList(); var finalResult = whenAllResult.ToList();
return finalResult; 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);
}
}
} }

View File

@ -34,7 +34,7 @@ namespace PoweredSoft.DynamicQuery
public long? NumberOfPages { get; set; } 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; } public List<IGroupQueryResult<TRecord>> Groups { get; set; }
} }