public async Task <LoadResult> LoadAsync() { if (Context.IsCountQuery) { return new LoadResult { totalCount = await ExecCountAsync() } } ; var result = new LoadResult(); if (Context.UseRemoteGrouping && Context.ShouldEmptyGroups) { var groupingResult = await ExecRemoteGroupingAsync(); EmptyGroups(groupingResult.Groups, Context.Group.Count); result.data = Paginate(groupingResult.Groups, Context.Skip, Context.Take); result.summary = groupingResult.Totals; result.totalCount = groupingResult.TotalCount; if (Context.RequireGroupCount) { result.groupCount = groupingResult.Groups.Count(); } } else { var deferPaging = Context.HasGroups || !Context.UseRemoteGrouping && !Context.SummaryIsTotalCountOnly && Context.HasSummary; Expression loadExpr; if (!deferPaging && Context.PaginateViaPrimaryKey && Context.Take > 0) { if (!Context.HasPrimaryKey) { throw new InvalidOperationException(nameof(DataSourceLoadOptionsBase.PaginateViaPrimaryKey) + " requires a primary key." + " Specify it via the " + nameof(DataSourceLoadOptionsBase.PrimaryKey) + " property."); } var loadKeysExpr = Builder.BuildLoadExpr(Source.Expression, true, selectOverride: Context.PrimaryKey); var keyTuples = await ExecExprAsync <AnonType>(loadKeysExpr); loadExpr = Builder.BuildLoadExpr(Source.Expression, false, filterOverride: FilterFromKeys(keyTuples)); } else { loadExpr = Builder.BuildLoadExpr(Source.Expression, !deferPaging); } if (Context.HasAnySelect) { await ContinueWithGroupingAsync( await ExecWithSelectAsync(loadExpr), result ); } else { await ContinueWithGroupingAsync( await ExecExprAsync <S>(loadExpr), result ); } if (deferPaging) { result.data = Paginate(result.data, Context.Skip, Context.Take); } if (Context.ShouldEmptyGroups) { EmptyGroups(result.data, Context.Group.Count); } } return(result); } async Task <IEnumerable <ExpandoObject> > ExecWithSelectAsync(Expression loadExpr) { if (Context.UseRemoteSelect) { return(SelectHelper.ConvertRemoteResult(await ExecExprAsync <AnonType>(loadExpr), Context.FullSelect)); } return(SelectHelper.Evaluate(await ExecExprAsync <S>(loadExpr), Context.FullSelect)); } async Task ContinueWithGroupingAsync <R>(IEnumerable <R> loadResult, LoadResult result) { var accessor = new DefaultAccessor <R>(); if (Context.HasGroups) { var groups = new GroupHelper <R>(accessor).Group(loadResult, Context.Group); if (Context.RequireGroupCount) { result.groupCount = groups.Count; } await ContinueWithAggregationAsync(groups, accessor, result); } else { await ContinueWithAggregationAsync(loadResult, accessor, result); } } async Task ContinueWithAggregationAsync <R>(IEnumerable data, IAccessor <R> accessor, LoadResult result) { if (Context.UseRemoteGrouping && !Context.SummaryIsTotalCountOnly && Context.HasSummary && !Context.HasGroups) { var groupingResult = await ExecRemoteGroupingAsync(); result.totalCount = groupingResult.TotalCount; result.summary = groupingResult.Totals; } else { var totalCount = -1; if (Context.RequireTotalCount || Context.SummaryIsTotalCountOnly) { totalCount = await ExecCountAsync(); } if (Context.RequireTotalCount) { result.totalCount = totalCount; } if (Context.SummaryIsTotalCountOnly) { result.summary = Enumerable.Repeat((object)totalCount, Context.TotalSummary.Count).ToArray(); } else if (Context.HasSummary) { data = Buffer <R>(data); result.summary = new AggregateCalculator <R>(data, accessor, Context.TotalSummary, Context.GroupSummary).Run(); } } result.data = data; } Task <int> ExecCountAsync() { var expr = Builder.BuildCountExpr(Source.Expression); #if DEBUG ExpressionWatcher?.Invoke(expr); #endif if (AsyncHelper != null) { return(AsyncHelper.CountAsync(expr)); } return(Task.FromResult(Source.Provider.Execute <int>(expr))); } async Task <RemoteGroupingResult> ExecRemoteGroupingAsync() { return(RemoteGroupTransformer.Run( typeof(S), await ExecExprAsync <AnonType>(Builder.BuildLoadGroupsExpr(Source.Expression)), Context.HasGroups ? Context.Group.Count : 0, Context.TotalSummary, Context.GroupSummary )); } Task <IEnumerable <R> > ExecExprAsync <R>(Expression expr) { #if DEBUG ExpressionWatcher?.Invoke(expr); #endif if (AsyncHelper != null) { var result = AsyncHelper.ToEnumerableAsync <R>(expr); #if DEBUG if (UseEnumerableOnce) { result = result.ContinueWith(t => (IEnumerable <R>) new EnumerableOnce <R>(t.Result)); } #endif return(result); } else { IEnumerable <R> result = Source.Provider.CreateQuery <R>(expr); #if DEBUG if (UseEnumerableOnce) { result = new EnumerableOnce <R>(result); } #endif return(Task.FromResult(result)); } } IList FilterFromKeys(IEnumerable <AnonType> keyTuples) { var result = new List <object>(); var key = Context.PrimaryKey; var keyLength = key.Count; foreach (var tuple in keyTuples) { if (result.Count > 0) { result.Add("or"); } void AddCondition(IList container, int index) { container.Add(new object[] { key[index], tuple[index] }); } if (keyLength == 1) { AddCondition(result, 0); } else { var group = new List <object>(); for (var i = 0; i < keyLength; i++) { AddCondition(group, i); } result.Add(group); } } return(result); }