IEnumerable<AnonType> ExecWithSelect(Expression loadExpr) { if(Options.UseRemoteSelect) return ExecExpr<AnonType>(Source, loadExpr); var inMemoryQuery = ForceExecution(ExecExpr<S>(Source, loadExpr)).AsQueryable(); var selectExpr = new SelectExpressionCompiler<S>(true).Compile(inMemoryQuery.Expression, Options.GetFullSelect()); return ExecExpr<AnonType>(inMemoryQuery, selectExpr); }
public LoadResult Load() { if (Options.IsCountQuery) { return new LoadResult { totalCount = ExecCount() } } ; var result = new LoadResult(); if (CanUseRemoteGrouping && ShouldEmptyGroups) { var groupingResult = ExecRemoteGrouping(); EmptyGroups(groupingResult.Groups, Options.Group.Length); result.data = Paginate(groupingResult.Groups, Options.Skip, Options.Take); result.summary = groupingResult.Totals; result.totalCount = groupingResult.TotalCount; if (Options.RequireGroupCount) { result.groupCount = groupingResult.Groups.Count(); } } else { if (!Options.HasPrimaryKey) { Options.PrimaryKey = Utils.GetPrimaryKey(typeof(S)); } if (!Options.HasPrimaryKey && !Options.HasDefaultSort && (Options.Skip > 0 || Options.Take > 0)) { if (Compat.IsEntityFramework(Source.Provider)) { Options.DefaultSort = EFSorting.FindSortableMember(typeof(S)); } else if (Compat.IsXPO(Source.Provider)) { Options.DefaultSort = "this"; } } var deferPaging = Options.HasGroups || !CanUseRemoteGrouping && !SummaryIsTotalCountOnly && Options.HasSummary; var loadExpr = Builder.BuildLoadExpr(Source.Expression, !deferPaging); if (Options.HasAnySelect) { ContinueWithGrouping( ExecWithSelect(loadExpr).Select(ProjectionToExpando), result ); } else { ContinueWithGrouping( ExecExpr <S>(Source, loadExpr), result ); } if (deferPaging) { result.data = Paginate(result.data, Options.Skip, Options.Take); } if (ShouldEmptyGroups) { EmptyGroups(result.data, Options.Group.Length); } } return(result); } IEnumerable <AnonType> ExecWithSelect(Expression loadExpr) { if (Options.UseRemoteSelect) { return(ExecExpr <AnonType>(Source, loadExpr)); } var inMemoryQuery = ForceExecution(ExecExpr <S>(Source, loadExpr)).AsQueryable(); var selectExpr = new SelectExpressionCompiler <S>(true).Compile(inMemoryQuery.Expression, Options.GetFullSelect()); return(ExecExpr <AnonType>(inMemoryQuery, selectExpr)); } void ContinueWithGrouping <R>(IEnumerable <R> loadResult, LoadResult result) { var accessor = new DefaultAccessor <R>(); if (Options.HasGroups) { var groups = new GroupHelper <R>(accessor).Group(loadResult, Options.Group); if (Options.RequireGroupCount) { result.groupCount = groups.Count; } ContinueWithAggregation(groups, accessor, result); } else { ContinueWithAggregation(loadResult, accessor, result); } } void ContinueWithAggregation <R>(IEnumerable data, IAccessor <R> accessor, LoadResult result) { if (CanUseRemoteGrouping && !SummaryIsTotalCountOnly && Options.HasSummary && !Options.HasGroups) { var groupingResult = ExecRemoteGrouping(); result.totalCount = groupingResult.TotalCount; result.summary = groupingResult.Totals; } else { var totalCount = -1; if (Options.RequireTotalCount || SummaryIsTotalCountOnly) { totalCount = ExecCount(); } if (Options.RequireTotalCount) { result.totalCount = totalCount; } if (SummaryIsTotalCountOnly) { result.summary = Enumerable.Repeat((object)totalCount, Options.TotalSummary.Length).ToArray(); } else if (Options.HasSummary) { data = Buffer <R>(data); result.summary = new AggregateCalculator <R>(data, accessor, Options.TotalSummary, Options.GroupSummary).Run(); } } result.data = data; } int ExecCount() { var expr = Builder.BuildCountExpr(Source.Expression); #if DEBUG Options.ExpressionWatcher?.Invoke(expr); #endif return(Source.Provider.Execute <int>(expr)); } RemoteGroupingResult ExecRemoteGrouping() { return(RemoteGroupTransformer.Run( ExecExpr <AnonType>(Source, Builder.BuildLoadGroupsExpr(Source.Expression)), Options.HasGroups ? Options.Group.Length : 0, Options.TotalSummary, Options.GroupSummary )); } IEnumerable <R> ExecExpr <R>(IQueryable <S> source, Expression expr) { IEnumerable <R> result = source.Provider.CreateQuery <R>(expr); #if DEBUG if (Options.UseEnumerableOnce) { result = new EnumerableOnce <R>(result); } Options.ExpressionWatcher?.Invoke(expr); #endif return(result); }
Expression BuildCore(Expression expr, bool paginate = false, bool isCountQuery = false, bool remoteGrouping = false) { var queryableType = typeof(Queryable); var genericTypeArguments = new[] { typeof(T) }; if (_loadOptions.HasFilter) { expr = Expression.Call(queryableType, "Where", genericTypeArguments, expr, Expression.Quote(new FilterExpressionCompiler <T>(_guardNulls, _stringToLower).Compile(_loadOptions.Filter))); } if (!isCountQuery) { if (!remoteGrouping) { if (_loadOptions.HasAnySort) { expr = new SortExpressionCompiler <T>(_guardNulls).Compile(expr, _loadOptions.GetFullSort()); } if (_loadOptions.HasAnySelect && _loadOptions.UseRemoteSelect) { expr = new SelectExpressionCompiler <T>(_guardNulls).Compile(expr, _loadOptions.GetFullSelect()); genericTypeArguments = expr.Type.GetGenericArguments(); } } else { expr = new RemoteGroupExpressionCompiler <T>(_guardNulls, _anonTypeNewTweaks, _loadOptions.Group, _loadOptions.TotalSummary, _loadOptions.GroupSummary).Compile(expr); } if (paginate) { if (_loadOptions.Skip > 0) { expr = Expression.Call(queryableType, "Skip", genericTypeArguments, expr, Expression.Constant(_loadOptions.Skip)); } if (_loadOptions.Take > 0) { expr = Expression.Call(queryableType, "Take", genericTypeArguments, expr, Expression.Constant(_loadOptions.Take)); } } } if (isCountQuery) { expr = Expression.Call(queryableType, "Count", genericTypeArguments, expr); } return(expr); }
/// <summary> /// core build query function. start point /// </summary> /// <param name="expr"></param> /// <param name="paginate"></param> /// <param name="isCountQuery"></param> /// <param name="remoteGrouping"></param> /// <returns></returns> Expression BuildCore(Expression expr, bool paginate = false, bool isCountQuery = false, bool remoteGrouping = false) { var queryableType = typeof(Queryable); var genericTypeArguments = new[] { typeof(T) }; // call expression with filter if (_loadOptions.HasFilter) { expr = Expression.Call(queryableType, "Where", genericTypeArguments, expr, Expression.Quote(new FilterExpressionCompiler <T>(_guardNulls).Compile(_loadOptions.Filter))); } if (!isCountQuery) { if (!remoteGrouping) { if (_loadOptions.HasAnySort) { expr = new SortExpressionCompiler <T>(_guardNulls).Compile(expr, _loadOptions.GetFullSort()); } if (_loadOptions.HasAnySelect && _loadOptions.UseRemoteSelect) { expr = new SelectExpressionCompiler <T>(_guardNulls).Compile(expr, _loadOptions.GetFullSelect()); #if (NET40) genericTypeArguments = expr.Type.GetGenericArguments(); #elif (NETSTANDARD1_0 || NETSTANDARD1_1 || NETSTANDARD1_2 || NETSTANDARD1_3 || NETSTANDARD1_4 || NETSTANDARD1_5 || NETSTANDARD1_6 || NETSTANDARD2_0) genericTypeArguments = expr.Type.GetTypeInfo().IsGenericTypeDefinition ? expr.Type.GetTypeInfo().GenericTypeParameters : expr.Type.GetTypeInfo().GenericTypeArguments; #elif (NETCOREAPP1_0 || NETCOREAPP1_1 || NETCOREAPP2_0 || NETCOREAPP2_1) IEnumerable <Type> arguments = expr.Type.IsGenericTypeDefinition ? expr.Type.GenericTypeParameters : expr.Type.GenericTypeArguments; genericTypeArguments = arguments.Select(x => x.GetTypeInfo()).ToArray(); #endif } } else { expr = new RemoteGroupExpressionCompiler <T>(_guardNulls, _loadOptions.Group, _loadOptions.TotalSummary, _loadOptions.GroupSummary).Compile(expr); } if (paginate) { if (_loadOptions.Skip > 0) { expr = Expression.Call(queryableType, "Skip", genericTypeArguments, expr, Expression.Constant(_loadOptions.Skip)); } if (_loadOptions.Take > 0) { expr = Expression.Call(queryableType, "Take", genericTypeArguments, expr, Expression.Constant(_loadOptions.Take)); } } } if (isCountQuery) { expr = Expression.Call(queryableType, "Count", genericTypeArguments, expr); } return(expr); }