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; }
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<T> interface. /// </summary> /// <typeparam name="T">The type of objects in the collection.</typeparam> /// <param name="source">A collection that implements the IQueryable<T> 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<T> interface. /// </summary> /// <typeparam name="T">The type of objects in the collection.</typeparam> /// <param name="source">A collection that implements the IEnumerable<T> 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); }
/// <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()); }
/// <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)); }
static Task <LoadResult> LoadAsync <T>(IQueryable <T> source, DataSourceLoadOptionsBase options, CancellationToken ct, bool sync) { return(new DataSourceLoaderImpl <T>(source, options, ct, sync).LoadAsync()); }