Async seems to work very well :)
This commit is contained in:
		
							parent
							
								
									23b45a00ac
								
							
						
					
					
						commit
						ce07c3f6d2
					
				
							
								
								
									
										138
									
								
								PoweredSoft.DynamicQuery.Test/AsyncTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								PoweredSoft.DynamicQuery.Test/AsyncTests.cs
									
									
									
									
									
										Normal 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);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Text;
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
using Microsoft.EntityFrameworkCore;
 | 
					using Microsoft.EntityFrameworkCore;
 | 
				
			||||||
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.ClientProtocol;
 | 
					using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.ClientProtocol;
 | 
				
			||||||
using Xunit.Sdk;
 | 
					using Xunit.Sdk;
 | 
				
			||||||
@ -21,5 +22,6 @@ namespace PoweredSoft.DynamicQuery.Test.Mock
 | 
				
			|||||||
            seedAction(testName);
 | 
					            seedAction(testName);
 | 
				
			||||||
            TestContextFor(testName, action);
 | 
					            TestContextFor(testName, action);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,8 @@
 | 
				
			|||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <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" />
 | 
					    <ProjectReference Include="..\PoweredSoft.DynamicQuery\PoweredSoft.DynamicQuery.csproj" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@ namespace PoweredSoft.DynamicQuery
 | 
				
			|||||||
    public class QueryHandlerAsync : QueryHandlerBase, IQueryHandlerAsync
 | 
					    public class QueryHandlerAsync : QueryHandlerBase, IQueryHandlerAsync
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public IAsyncQueryableFactory AsyncQueryableFactory { get; }
 | 
					        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 });
 | 
					        internal Task<IQueryExecutionResult> ExecuteAsyncReflected(CancellationToken cancellationToken) => (Task<IQueryExecutionResult>)ExecuteAsyncGeneric.MakeGenericMethod(QueryableUnderlyingType).Invoke(this, new object[] { cancellationToken });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public QueryHandlerAsync(IAsyncQueryableFactory asyncQueryableFactory)
 | 
					        public QueryHandlerAsync(IAsyncQueryableFactory asyncQueryableFactory)
 | 
				
			||||||
@ -20,7 +20,7 @@ namespace PoweredSoft.DynamicQuery
 | 
				
			|||||||
            AsyncQueryableFactory = asyncQueryableFactory;
 | 
					            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>();
 | 
					            CommonBeforeExecute<T>();
 | 
				
			||||||
            return HasGrouping ? ExecuteAsyncGrouping<T>(cancellationToken) : ExecuteAsyncNoGrouping<T>(cancellationToken);
 | 
					            return HasGrouping ? ExecuteAsyncGrouping<T>(cancellationToken) : ExecuteAsyncNoGrouping<T>(cancellationToken);
 | 
				
			||||||
@ -120,7 +120,7 @@ namespace PoweredSoft.DynamicQuery
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                IQueryable selectExpression = CreateFetchAggregateSelectExpression<T>(fg, previousGroups);
 | 
					                IQueryable selectExpression = CreateFetchAggregateSelectExpression<T>(fg, previousGroups);
 | 
				
			||||||
                var selectExpressionCasted = selectExpression.Cast<DynamicClass>();
 | 
					                var selectExpressionCasted = selectExpression.Cast<DynamicClass>();
 | 
				
			||||||
                var aggregateResult = AsyncQueryableFactory.ToListAsync<DynamicClass>(selectExpressionCasted, cancellationToken);
 | 
					                var aggregateResult = AsyncQueryableFactory.ToListAsync(selectExpressionCasted, cancellationToken);
 | 
				
			||||||
                previousGroups.Add(fg);
 | 
					                previousGroups.Add(fg);
 | 
				
			||||||
                return aggregateResult;
 | 
					                return aggregateResult;
 | 
				
			||||||
            }));
 | 
					            }));
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user