コード例 #1
0
        /// <summary>
        /// Execute group-by without aggregation on the results.
        /// </summary>
        /// <param name="query">The collection to group.</param>
        /// <param name="maxResults">The max number of elements in a result set.</param>
        /// <param name="transformation">The group-by transformation as <see cref="ApplyGroupbyClause"/>.</param>
        /// <param name="keyType">The key type to group by.</param>
        /// <param name="propertiesToGroupByExpressions">Lambda expression that represents access to the properties to group by.</param>
        /// <returns>The results of the group by transformation as <see cref="IQueryable"/>.</returns>
        public IQueryable DoGroupBy(IQueryable query, int maxResults, ApplyGroupbyClause transformation, Type keyType, IEnumerable <LambdaExpression> propertiesToGroupByExpressions)
        {
            var propToGroupBy = (propertiesToGroupByExpressions != null)
                ? propertiesToGroupByExpressions.ToArray()
                : null;
            var    keySelector = this.GetGroupByProjectionLambda(transformation.SelectedStatements.ToArray(), keyType, propToGroupBy);
            object comparer    = keyType.GetProperty("ComparerInstance").GetValue(null);
            var    results     = ExpressionHelpers.GroupBy(query, keySelector, this.Context.ElementClrType, keyType, comparer);

            var keys = this.GetGroupingKeys(results, keyType, this.Context.ElementClrType);

            // if group by is not supported in this IQueriable provider convert the grouping into memory implementation
            object convertedResult = null;
            int    numberOfTempResults;

            if (QueriableProviderAdapter.ConvertionIsRequiredAsExpressionIfNotSupported(keys, maxResults, out convertedResult, out numberOfTempResults))
            {
                keys = convertedResult as IQueryable;
            }

            var keysToReturn = ExpressionHelpers.Distinct(keyType, keys);

            return(keysToReturn);
        }
コード例 #2
0
        /// <summary>
        /// Execute group-by with aggregation on the results.
        /// </summary>
        /// <param name="query">The collection to group.</param>
        /// <param name="maxResults">The max number of elements in a result set.</param>
        /// <param name="transformation">The group-by transformation as <see cref="ApplyGroupbyClause"/>.</param>
        /// <param name="keyType">The key type to group by.</param>
        /// <param name="propertiesToGroupByExpressions">Lambda expression that represents access to the properties to group by.</param>
        /// <param name="propertyToAggregateExpression">Lambda expression that represents access to the property to aggregate.</param>
        /// <param name="keys">Output the collection keys of the grouped results.</param>
        /// <param name="aggragatedValues">Output the aggregated results.</param>
        public void DoAggregatedGroupBy(
            IQueryable query, int maxResults, ApplyGroupbyClause transformation,
            Type keyType, IEnumerable <LambdaExpression> propertiesToGroupByExpressions, LambdaExpression propertyToAggregateExpression, out IQueryable keys, out object[] aggragatedValues)
        {
            var propToGroupBy = (propertiesToGroupByExpressions != null)
               ? propertiesToGroupByExpressions.ToArray()
               : null;
            var    keySelector               = this.GetGroupByProjectionLambda(transformation.SelectedStatements.ToArray(), keyType, propToGroupBy);
            object comparer                  = keyType.GetProperty("ComparerInstance").GetValue(null);
            var    groupingResults           = ExpressionHelpers.GroupBy(query, keySelector, this.Context.ElementClrType, keyType, comparer);
            var    aggregationImplementation =
                AggregationMethodsImplementations.GetAggregationImplementation(transformation.Aggregate.AggregationMethod);

            // if group by is not supported in this IQueriable provider convert the grouping into memory implementation
            object convertedResult = null;
            int    numberOfTempResults;

            if (QueriableProviderAdapter.ConvertionIsRequiredAsExpressionIfNotSupported(groupingResults, maxResults, out convertedResult, out numberOfTempResults))
            {
                groupingResults = convertedResult as IQueryable;
            }

            var resType = typeof(List <>).MakeGenericType(this.Context.ElementClrType);

            keys = this.GetGroupingKeys(groupingResults, keyType, this.Context.ElementClrType);
            var groupedValues = this.GetGroupingValues(groupingResults, keyType, resType, this.Context.ElementClrType);

            // In case of paging due to memory execution of unsupported functions keys may not be distinct.
            // Here we make sure that keys are distinct and all values that belong to a key are written to the right list.
            List <object> distictKeys;
            List <object> groupedValuesPerKey;

            if (numberOfTempResults > 1)
            {
                this.CombineValuesListsPerKey(keys.AllElements(), groupedValues.AllElements(), out distictKeys, out groupedValuesPerKey);
                keys = distictKeys.AsQueryable();
            }
            groupedValuesPerKey = groupedValues.AllElements();
            int numberOfResults = groupedValuesPerKey.Count;

            var tmpAggragatedValues = new object[numberOfResults];
            var projectionLambda    = AggregationImplementationBase.GetProjectionLambda(this.Context.ElementClrType, transformation.Aggregate, propertyToAggregateExpression);

            string[] aggregationParams = AggregationImplementationBase.GetAggregationParams(transformation.Aggregate.AggregationMethod);

            Parallel.For(0, numberOfResults, (i =>
            {
                IQueryable valuesAsQueryable;
                if (groupedValuesPerKey[i] is IEnumerable <object> )
                {
                    valuesAsQueryable = ExpressionHelpers.Cast(this.Context.ElementClrType,
                                                               (groupedValuesPerKey[i] as IEnumerable <Object>).AsQueryable());
                }
                else
                {
                    valuesAsQueryable = ExpressionHelpers.Cast(this.Context.ElementClrType,
                                                               (new List <Object>()
                    {
                        groupedValuesPerKey[i]
                    }).AsQueryable());
                }

                IQueryable queryToUse = valuesAsQueryable;
                if (transformation.Aggregate.AggregatableProperty.Contains('/'))
                {
                    queryToUse = AggregationImplementationBase.FilterNullValues(query, this.Context.ElementClrType,
                                                                                transformation.Aggregate);
                }

                var aggragationResult = aggregationImplementation.DoAggregatinon(this.Context.ElementClrType, queryToUse,
                                                                                 transformation.Aggregate, projectionLambda, aggregationParams);
                tmpAggragatedValues[i] = aggragationResult;
            }));

            aggragatedValues = tmpAggragatedValues;
        }