Async seems to work very well :)

This commit is contained in:
David Lebee 2018-12-06 23:08:16 -06:00
parent 23b45a00ac
commit ce07c3f6d2
4 changed files with 145 additions and 3 deletions

View File

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

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.ClientProtocol;
using Xunit.Sdk;
@ -21,5 +22,6 @@ namespace PoweredSoft.DynamicQuery.Test.Mock
seedAction(testName);
TestContextFor(testName, action);
}
}
}

View File

@ -16,6 +16,8 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Data\PoweredSoft.Data.Core\PoweredSoft.Data.Core.csproj" />
<ProjectReference Include="..\..\Data\PoweredSoft.Data.EntityFrameworkCore\PoweredSoft.Data.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\PoweredSoft.DynamicQuery\PoweredSoft.DynamicQuery.csproj" />
</ItemGroup>

View File

@ -12,7 +12,7 @@ namespace PoweredSoft.DynamicQuery
public class QueryHandlerAsync : QueryHandlerBase, IQueryHandlerAsync
{
public IAsyncQueryableFactory AsyncQueryableFactory { get; }
internal MethodInfo ExecuteAsyncGeneric = typeof(QueryHandler).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic).First(t => t.Name == "ExecuteAsync" && t.IsGenericMethod);
internal MethodInfo ExecuteAsyncGeneric = typeof(QueryHandlerAsync).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic).First(t => t.Name == "ExecuteAsync" && t.IsGenericMethod);
internal Task<IQueryExecutionResult> ExecuteAsyncReflected(CancellationToken cancellationToken) => (Task<IQueryExecutionResult>)ExecuteAsyncGeneric.MakeGenericMethod(QueryableUnderlyingType).Invoke(this, new object[] { cancellationToken });
public QueryHandlerAsync(IAsyncQueryableFactory asyncQueryableFactory)
@ -20,7 +20,7 @@ namespace PoweredSoft.DynamicQuery
AsyncQueryableFactory = asyncQueryableFactory;
}
public Task<IQueryExecutionResult> ExecuteAsync<T>(IQueryable queryable, IQueryCriteria criteria, CancellationToken cancellationToken = default(CancellationToken))
protected virtual Task<IQueryExecutionResult> ExecuteAsync<T>(CancellationToken cancellationToken = default(CancellationToken))
{
CommonBeforeExecute<T>();
return HasGrouping ? ExecuteAsyncGrouping<T>(cancellationToken) : ExecuteAsyncNoGrouping<T>(cancellationToken);
@ -120,7 +120,7 @@ namespace PoweredSoft.DynamicQuery
{
IQueryable selectExpression = CreateFetchAggregateSelectExpression<T>(fg, previousGroups);
var selectExpressionCasted = selectExpression.Cast<DynamicClass>();
var aggregateResult = AsyncQueryableFactory.ToListAsync<DynamicClass>(selectExpressionCasted, cancellationToken);
var aggregateResult = AsyncQueryableFactory.ToListAsync(selectExpressionCasted, cancellationToken);
previousGroups.Add(fg);
return aggregateResult;
}));