static bool ShouldUseRemoteGrouping(QueryProviderInfo provider, DataSourceLoadOptionsBase options)
        {
            if (provider.IsLinqToObjects)
            {
                return(false);
            }

            if (provider.IsEFCore)
            {
                // https://github.com/aspnet/EntityFrameworkCore/issues/2341
                // https://github.com/aspnet/EntityFrameworkCore/issues/11993
                // https://github.com/aspnet/EntityFrameworkCore/issues/11999
                if (provider.Version < new Version(2, 2, 0))
                {
                    return(false);
                }

                bool HasAvg(SummaryInfo[] summary)
                {
                    return(summary != null && summary.Any(i => i.SummaryType == "avg"));
                }

                #warning Remove with https://github.com/aspnet/EntityFrameworkCore/issues/11711 fix
                if (HasAvg(options.TotalSummary) || HasAvg(options.GroupSummary))
                {
                    return(false);
                }
            }

            return(true);
        }
 public DataSourceExpressionBuilder(DataSourceLoadOptionsBase loadOptions, bool guardNulls = false, bool stringToLower = false, AnonTypeNewTweaks anonTypeNewTweaks = null)
 {
     _loadOptions       = loadOptions;
     _guardNulls        = guardNulls;
     _stringToLower     = stringToLower;
     _anonTypeNewTweaks = anonTypeNewTweaks;
 }
        public DataSourceLoaderImpl(IQueryable <S> source, DataSourceLoadOptionsBase options, CancellationToken cancellationToken, bool sync)
        {
            var providerInfo = new QueryProviderInfo(source.Provider);
            var guardNulls   = providerInfo.IsLinqToObjects;

            if (!sync)
            {
                AsyncHelper = new AsyncHelper(source.Provider, providerInfo, cancellationToken);
            }

#if DEBUG
            ExpressionWatcher = options.ExpressionWatcher;
            UseEnumerableOnce = options.UseEnumerableOnce;
            guardNulls        = guardNulls && !options.SuppressGuardNulls;
#endif

            Source  = source;
            Context = new DataSourceLoadContext(options, providerInfo, typeof(S));
            Builder = new DataSourceExpressionBuilder <S>(
                Context,
                guardNulls,
                new AnonTypeNewTweaks {
                AllowEmpty         = !providerInfo.IsL2S,
                AllowUnusedMembers = !providerInfo.IsL2S
            }
                );
        }
        public DataSourceLoaderImpl(IQueryable <S> source, DataSourceLoadOptionsBase options)
        {
            QueryProviderInfo       = new QueryProviderInfo(source.Provider);
            Builder                 = new DataSourceExpressionBuilder <S>(options, QueryProviderInfo.IsLinqToObjects);
            ShouldEmptyGroups       = options.HasGroups && !options.Group.Last().GetIsExpanded();
            CanUseRemoteGrouping    = options.RemoteGrouping ?? ShouldUseRemoteGrouping(QueryProviderInfo, options);
            SummaryIsTotalCountOnly = !options.HasGroupSummary && options.HasSummary && options.TotalSummary.All(i => i.SummaryType == AggregateName.COUNT);

            Source  = source;
            Options = options;
        }
        public DataSourceLoaderImpl(IQueryable source, DataSourceLoadOptionsBase options, CancellationToken cancellationToken, bool sync)
        {
            var providerInfo = new QueryProviderInfo(source.Provider);

            Source         = source;
            Context        = new DataSourceLoadContext(options, providerInfo, Source.ElementType);
            CreateExecutor = expr => new ExpressionExecutor(Source.Provider, expr, providerInfo, cancellationToken, sync, options.AllowAsyncOverSync);

#if DEBUG
            ExpressionWatcher = options.ExpressionWatcher;
            UseEnumerableOnce = options.UseEnumerableOnce;
#endif
        }
        public DataSourceLoaderImpl(IQueryable<S> source, DataSourceLoadOptionsBase options) {
            var isLinqToObjects = source is EnumerableQuery;

            // Until https://github.com/aspnet/EntityFramework/issues/2341 is implemented
            // local grouping is more efficient for EF Core
            var preferLocalGrouping = Compat.IsEFCore(source.Provider);

            Builder = new DataSourceExpressionBuilder<S>(options, isLinqToObjects);
            ShouldEmptyGroups = options.HasGroups && !options.Group.Last().GetIsExpanded();
            CanUseRemoteGrouping = options.RemoteGrouping ?? !(isLinqToObjects || preferLocalGrouping);
            SummaryIsTotalCountOnly = !options.HasGroupSummary && options.HasSummary && options.TotalSummary.All(i => i.SummaryType == AggregateName.COUNT);

            Source = source;
            Options = options;
        }
Esempio n. 7
0
        public DataSourceLoaderImpl(IQueryable <S> source, DataSourceLoadOptionsBase options)
        {
            QueryProviderInfo = new QueryProviderInfo(source.Provider);
            Builder           = new DataSourceExpressionBuilder <S>(
                options,
                QueryProviderInfo.IsLinqToObjects,
                options.StringToLower.GetValueOrDefault(QueryProviderInfo.IsLinqToObjects),
                new AnonTypeNewTweaks {
                AllowEmpty         = !QueryProviderInfo.IsL2S,
                AllowUnusedMembers = !QueryProviderInfo.IsL2S
            }
                );
            ShouldEmptyGroups       = options.HasGroups && !options.Group.Last().GetIsExpanded();
            CanUseRemoteGrouping    = options.RemoteGrouping ?? ShouldUseRemoteGrouping(QueryProviderInfo, options);
            SummaryIsTotalCountOnly = !options.HasGroupSummary && options.HasSummary && options.TotalSummary.All(i => i.SummaryType == AggregateName.COUNT);

            Source  = source;
            Options = options;
        }
        public DataSourceLoaderImpl(IQueryable <S> source, DataSourceLoadOptionsBase options)
        {
#if DEBUG
            ExpressionWatcher = options.ExpressionWatcher;
            UseEnumerableOnce = options.UseEnumerableOnce;
#endif

            var providerInfo = new QueryProviderInfo(source.Provider);

            Source  = source;
            Context = new DataSourceLoadContext(options, providerInfo, typeof(S));
            Builder = new DataSourceExpressionBuilder <S>(
                Context,
                providerInfo.IsLinqToObjects,
                new AnonTypeNewTweaks {
                AllowEmpty         = !providerInfo.IsL2S,
                AllowUnusedMembers = !providerInfo.IsL2S
            }
                );
        }
 public DataSourceExpressionBuilder(DataSourceLoadOptionsBase loadOptions, bool guardNulls)
 {
     _loadOptions = loadOptions;
     _guardNulls  = guardNulls;
 }
 /// <summary>
 /// Loads data from a collection that implements the IQueryable&lt;T&gt; interface.
 /// </summary>
 /// <typeparam name="T">The type of objects in the collection.</typeparam>
 /// <param name="source">A collection that implements the IQueryable&lt;T&gt; interface.</param>
 /// <param name="options">Data processing settings when loading data.</param>
 /// <returns>The load result.</returns>
 public static LoadResult Load <T>(IQueryable <T> source, DataSourceLoadOptionsBase options)
 {
     return(new DataSourceLoaderImpl <T>(source, options).Load());
 }
 public DataSourceLoadContext(DataSourceLoadOptionsBase options, QueryProviderInfo providerInfo, Type itemType)
 {
     _options      = options;
     _providerInfo = providerInfo;
     _itemType     = itemType;
 }
        public static object Load <T>(IQueryable <T> source, DataSourceLoadOptionsBase options)
        {
            var isLinqToObjects = source is EnumerableQuery;
            var builder         = new DataSourceExpressionBuilder <T>(options, isLinqToObjects);

            if (options.IsCountQuery)
            {
                return(builder.BuildCountExpr().Compile()(source));
            }

            var accessor             = new DefaultAccessor <T>();
            var result               = new DataSourceLoadResult();
            var emptyGroups          = options.HasGroups && !options.Group.Last().GetIsExpanded();
            var canUseRemoteGrouping = options.RemoteGrouping.HasValue ? options.RemoteGrouping.Value : !isLinqToObjects;

            if (canUseRemoteGrouping && emptyGroups)
            {
                var groupingResult = ExecRemoteGrouping(source, builder, options);

                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(T));
                }

                if (!options.HasPrimaryKey && (options.Skip > 0 || options.Take > 0) && Compat.IsEntityFramework(source.Provider))
                {
                    options.DefaultSort = EFSorting.FindSortableMember(typeof(T));
                }

                var deferPaging = options.HasGroups || options.HasSummary && !canUseRemoteGrouping;
                var queryResult = ExecQuery(builder.BuildLoadExpr(!deferPaging).Compile(), source, options);

                IEnumerable data = queryResult;

                if (options.HasGroups)
                {
                    data = new GroupHelper <T>(accessor).Group(queryResult, options.Group);
                    if (options.RequireGroupCount)
                    {
                        result.groupCount = (data as IList).Count;
                    }
                }

                if (canUseRemoteGrouping && options.HasSummary && !options.HasGroups)
                {
                    var groupingResult = ExecRemoteGrouping(source, builder, options);
                    result.totalCount = groupingResult.TotalCount;
                    result.summary    = groupingResult.Totals;
                }
                else
                {
                    if (options.RequireTotalCount)
                    {
                        result.totalCount = builder.BuildCountExpr().Compile()(source);
                    }

                    if (options.HasSummary)
                    {
                        data           = Buffer <T>(data);
                        result.summary = new AggregateCalculator <T>(data, accessor, options.TotalSummary, options.GroupSummary).Run();
                    }
                }

                if (deferPaging)
                {
                    data = Paginate(data, options.Skip, options.Take);
                }

                if (emptyGroups)
                {
                    EmptyGroups(data, options.Group.Length);
                }

                result.data = data;
            }

            if (result.IsDataOnly())
            {
                return(result.data);
            }

            return(result);
        }
 /// <summary>
 /// Loads data from a collection that implements the IEnumerable&lt;T&gt; interface.
 /// </summary>
 /// <typeparam name="T">The type of objects in the collection.</typeparam>
 /// <param name="source">A collection that implements the IEnumerable&lt;T&gt; interface.</param>
 /// <param name="options">Data processing settings when loading data.</param>
 /// <returns>The load result.</returns>
 public static LoadResult Load <T>(IEnumerable <T> source, DataSourceLoadOptionsBase options)
 {
     return(Load(source.AsQueryable(), options));
 }
 static RemoteGroupingResult ExecRemoteGrouping <T>(IQueryable <T> source, DataSourceExpressionBuilder <T> builder, DataSourceLoadOptionsBase options)
 {
     return(RemoteGroupTransformer.Run(
                ExecQuery(builder.BuildLoadGroupsExpr().Compile(), source, options),
                options.HasGroups ? options.Group.Length : 0,
                options.TotalSummary,
                options.GroupSummary
                ));
 }
        static IQueryable <R> ExecQuery <S, R>(Func <IQueryable <S>, IQueryable <R> > query, IQueryable <S> source, DataSourceLoadOptionsBase options)
        {
            var result = query(source);

#if DEBUG
            if (options.UseQueryableOnce)
            {
                result = new QueryableOnce <R>(result);
            }

            if (options.ExpressionWatcher != null)
            {
                options.ExpressionWatcher(result.Expression);
            }
#endif

            return(result);
        }
Esempio n. 16
0
 /// <summary>
 /// Loads data from a collection that implements the <see cref="System.Linq.IQueryable{T}"/> interface.
 /// 从实现T接口的集合加载数据。
 /// </summary>
 /// <typeparam name="T">
 /// The type of objects in the collection.
 /// 集合中对象的类型。
 /// </typeparam>
 /// <param name="source">
 /// A collection that implements the <see cref="System.Linq.IQueryable{T}"/> interface.
 /// 实现System.Linq.IQueryable接口的集合。
 /// </param>
 /// <param name="options">
 /// Data processing settings when loading data.
 /// 加载数据时的数据处理设置。
 /// </param>
 /// <returns>
 /// The load result.
 /// 加载结果。
 /// </returns>
 public static LoadResult Load <T>(IQueryable <T> source, DataSourceLoadOptionsBase options)
 {
     return(LoadAsync(source, options, CancellationToken.None, true).GetAwaiter().GetResult());
 }
Esempio n. 17
0
 /// <summary>
 /// Asynchronously loads data from a collection that implements the <see cref="System.Linq.IQueryable{T}"/> interface.
 /// 从实现System.Linq.IQueryable接口的集合异步加载数据。
 /// </summary>
 /// <typeparam name="T">
 /// The type of objects in the collection.
 /// 集合中对象的类型。
 /// </typeparam>
 /// <param name="source">
 /// A collection that implements the <see cref="System.Linq.IQueryable{T}"/> interface.
 /// 实现System.Linq.IQueryable{T}接口的集合。
 /// </param>
 /// <param name="options">
 /// Data processing settings when loading data.
 /// 加载数据时的数据处理设置。
 /// </param>
 /// <param name="cancellationToken">
 /// A <see cref="System.Threading.CancellationToken"/> object that delivers a cancellation notice to the running operation.
 /// 向正在运行的操作发送取消通知的System.Threading.CancellationToken对象。
 /// </param>
 /// <returns>
 /// A <see cref="System.Threading.Tasks.Task{TResult}"/> object that represents the asynchronous operation.
 /// The task result contains the load result.
 /// 表示异步操作的System.Threading.Tasks.Task{TResult}对象。任务结果包含加载结果。
 /// </returns>
 public static Task <LoadResult> LoadAsync <T>(IQueryable <T> source, DataSourceLoadOptionsBase options, CancellationToken cancellationToken = default(CancellationToken))
 {
     return(LoadAsync(source, options, cancellationToken, false));
 }
Esempio n. 18
0
 static Task <LoadResult> LoadAsync <T>(IQueryable <T> source, DataSourceLoadOptionsBase options, CancellationToken ct, bool sync)
 {
     return(new DataSourceLoaderImpl <T>(source, options, ct, sync).LoadAsync());
 }