ready for version 2
This commit is contained in:
parent
9e6dc08e53
commit
dc9c7e1674
@ -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;r=g&amp;d=retro</PackageIconUrl>
|
<PackageIconUrl>https://secure.gravatar.com/avatar/4e32f73820c16718909a06c2927f1f8b?s=512&amp;r=g&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>
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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;r=g&amp;d=retro</PackageIconUrl>
|
<PackageIconUrl>https://secure.gravatar.com/avatar/4e32f73820c16718909a06c2927f1f8b?s=512&amp;r=g&amp;d=retro</PackageIconUrl>
|
||||||
<Product>PoweredSoft.DynamicQuery.Core</Product>
|
<Product>PoweredSoft.DynamicQuery.Core</Product>
|
||||||
<Description>core abstractions</Description>
|
<Description>core abstractions</Description>
|
||||||
|
@ -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);
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
//}
|
}
|
||||||
|
@ -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;r=g&amp;d=retro</PackageIconUrl>
|
<PackageIconUrl>https://secure.gravatar.com/avatar/4e32f73820c16718909a06c2927f1f8b?s=512&amp;r=g&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>
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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; }
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user