Exemplo n.º 1
0
        public void BindApplyWithAggregateShouldReturnApplyClause()
        {
            IEnumerable <QueryToken> tokens = _parser.ParseApply("aggregate(UnitPrice with sum as TotalPrice)");

            ApplyBinder binder = new ApplyBinder(FakeBindMethods.BindSingleComplexProperty, _bindingState);
            ApplyClause actual = binder.BindApply(tokens);

            actual.Should().NotBeNull();
            actual.Transformations.Should().HaveCount(1);

            List <TransformationNode>   transformations = actual.Transformations.ToList();
            AggregateTransformationNode aggregate       = transformations[0] as AggregateTransformationNode;

            aggregate.Should().NotBeNull();
            aggregate.Kind.Should().Be(TransformationNodeKind.Aggregate);
            aggregate.AggregateExpressions.Should().NotBeNull();
            aggregate.AggregateExpressions.Should().HaveCount(1);

            List <AggregateExpressionBase> statements = aggregate.AggregateExpressions.ToList();
            AggregateExpression            statement  = statements[0] as AggregateExpression;

            statement.Should().NotBeNull();
            VerifyIsFakeSingleValueNode(statement.Expression);
            statement.Method.Should().Be(AggregationMethod.Sum);
            statement.Alias.Should().Be("TotalPrice");
        }
        private MethodCallExpression ApplyAggregate(Expression source, AggregateTransformationNode transformation)
        {
            Type sourceType = OeExpressionHelper.GetCollectionItemType(source.Type);
            ParameterExpression sourceParameter = Expression.Parameter(sourceType);
            ParameterExpression lambdaParameter = sourceParameter;

            var expressions = new List <Expression>();

            if (sourceType.GetGenericTypeDefinition() == typeof(IGrouping <,>))
            {
                PropertyInfo     keyProperty = sourceType.GetTypeInfo().GetProperty(nameof(IGrouping <Object, Object> .Key));
                MemberExpression key         = Expression.Property(sourceParameter, keyProperty);
                expressions.Add(key);

                lambdaParameter = Expression.Parameter(sourceType.GetTypeInfo().GetGenericArguments()[1]);
            }

            var visitor = CreateVisitor(lambdaParameter);

            foreach (AggregateExpression aggExpression in transformation.Expressions)
            {
                Expression           e                 = visitor.TranslateNode(aggExpression.Expression);
                LambdaExpression     aggLambda         = Expression.Lambda(e, lambdaParameter);
                MethodCallExpression aggCallExpression = AggCallExpression(aggExpression.Method, sourceParameter, aggLambda);
                expressions.Add(aggCallExpression);

                _aggProperties.Add(CreateEdmProperty(_visitor.EdmModel, aggCallExpression.Type, aggExpression.Alias, false));
            }

            NewExpression    newExpression    = OeExpressionHelper.CreateTupleExpression(expressions);
            MethodInfo       selectMethodInfo = OeMethodInfoHelper.GetSelectMethodInfo(sourceType, newExpression.Type);
            LambdaExpression lambda           = Expression.Lambda(newExpression, sourceParameter);

            return(Expression.Call(selectMethodInfo, source, lambda));
        }
Exemplo n.º 3
0
        public void BindApplyWithEntitySetAggregationReturnApplyClause()
        {
            IEnumerable <QueryToken> tokens =
                _parser.ParseApply(
                    "groupby((LifeTime),aggregate(MyPaintings($count as Count)))");

            BindingState   state         = new BindingState(_configuration);
            MetadataBinder metadataBiner = new MetadataBinder(_bindingState);

            ApplyBinder binder = new ApplyBinder(metadataBiner.Bind, _bindingState);
            ApplyClause actual = binder.BindApply(tokens);

            actual.Should().NotBeNull();
            actual.Transformations.Should().HaveCount(1);

            GroupByTransformationNode groupBy = actual.Transformations.First() as GroupByTransformationNode;

            groupBy.Should().NotBeNull();
            groupBy.GroupingProperties.Should().HaveCount(1);

            AggregateTransformationNode aggregate = groupBy.ChildTransformations as AggregateTransformationNode;

            aggregate.Should().NotBeNull();
            aggregate.AggregateExpressions.Should().HaveCount(1);

            EntitySetAggregateExpression entitySetAggregate = aggregate.AggregateExpressions.First() as EntitySetAggregateExpression;

            entitySetAggregate.Should().NotBeNull();
        }
Exemplo n.º 4
0
        public void BindApplyWithExpandReturnApplyClause()
        {
            IEnumerable <QueryToken> tokens =
                _parser.ParseApply(
                    "expand(MyPaintings, filter(FrameColor eq 'Red'))/groupby((LifeTime),aggregate(MyPaintings($count as Count)))");

            BindingState   state         = new BindingState(_configuration);
            MetadataBinder metadataBiner = new MetadataBinder(_bindingState);

            ApplyBinder binder = new ApplyBinder(metadataBiner.Bind, _bindingState, V4configuration, new ODataPathInfo(HardCodedTestModel.GetPersonType(), HardCodedTestModel.GetPeopleSet()));
            ApplyClause actual = binder.BindApply(tokens);

            Assert.NotNull(actual);
            Assert.Equal(2, actual.Transformations.Count());

            ExpandTransformationNode expand = Assert.IsType <ExpandTransformationNode>(actual.Transformations.First());

            Assert.NotNull(expand.ExpandClause);
            ExpandedNavigationSelectItem expandItem = Assert.IsType <ExpandedNavigationSelectItem>(Assert.Single(expand.ExpandClause.SelectedItems));

            Assert.Equal("Paintings", expandItem.NavigationSource.Name);
            Assert.NotNull(expandItem.FilterOption);

            GroupByTransformationNode groupBy = Assert.IsType <GroupByTransformationNode>(actual.Transformations.Last());

            Assert.Single(groupBy.GroupingProperties);

            AggregateTransformationNode aggregate = Assert.IsType <AggregateTransformationNode>(groupBy.ChildTransformations);

            Assert.IsType <EntitySetAggregateExpression>(Assert.Single(aggregate.AggregateExpressions));
        }
Exemplo n.º 5
0
        public void BindApplyWitMultipleTokensShouldReturnApplyClause()
        {
            IEnumerable <QueryToken> tokens =
                _parser.ParseApply(
                    "groupby((ID, SSN, LifeTime))/aggregate(LifeTime with sum as TotalLife)/groupby((TotalLife))/aggregate(TotalLife with sum as TotalTotalLife)");

            BindingState   state         = new BindingState(_configuration);
            MetadataBinder metadataBiner = new MetadataBinder(_bindingState);

            ApplyBinder binder = new ApplyBinder(metadataBiner.Bind, _bindingState);
            ApplyClause actual = binder.BindApply(tokens);

            actual.Should().NotBeNull();
            actual.Transformations.Should().HaveCount(4);

            List <TransformationNode> transformations = actual.Transformations.ToList();
            GroupByTransformationNode firstGroupBy    = transformations[0] as GroupByTransformationNode;

            firstGroupBy.Should().NotBeNull();
            TransformationNode firstAggregate = transformations[1] as AggregateTransformationNode;

            firstAggregate.Should().NotBeNull();
            TransformationNode scecondGroupBy = transformations[2] as GroupByTransformationNode;

            scecondGroupBy.Should().NotBeNull();
            AggregateTransformationNode scecondAggregate = transformations[3] as AggregateTransformationNode;

            scecondAggregate.Should().NotBeNull();
        }
Exemplo n.º 6
0
        private MethodCallExpression ApplyAggregate(Expression source, AggregateTransformationNode transformation)
        {
            Type sourceType = OeExpressionHelper.GetCollectionItemType(source.Type);
            ParameterExpression sourceParameter = Expression.Parameter(sourceType);
            ParameterExpression lambdaParameter = sourceParameter;

            var  expressions = new List <Expression>();
            bool isGroupBy   = sourceType.GetGenericTypeDefinition() == typeof(IGrouping <,>);

            if (isGroupBy)
            {
                PropertyInfo     keyProperty = sourceType.GetProperty(nameof(IGrouping <Object, Object> .Key)) !;
                MemberExpression key         = Expression.Property(sourceParameter, keyProperty);
                expressions.Add(key);

                lambdaParameter = Expression.Parameter(sourceType.GetGenericArguments()[1]);
            }

            var visitor = CreateVisitor(lambdaParameter);

            foreach (AggregateExpressionBase aggExpressionBase in transformation.AggregateExpressions)
            {
                if (aggExpressionBase is AggregateExpression aggExpression)
                {
                    MethodCallExpression aggCallExpression;
                    if (aggExpression.Method == AggregationMethod.VirtualPropertyCount)
                    {
                        aggCallExpression = CountExpression(sourceParameter);
                    }
                    else
                    {
                        Expression expression = visitor.TranslateNode(aggExpression.Expression);
                        if (isGroupBy && expression is MemberExpression propertyExpression)
                        {
                            MemberExpression?keyPropertyExpression = FindInGroupByKey(source, expressions[0], propertyExpression);
                            if (keyPropertyExpression != null)
                            {
                                expression = keyPropertyExpression;
                            }
                        }
                        LambdaExpression aggLambda = Expression.Lambda(expression, lambdaParameter);
                        aggCallExpression = AggCallExpression(aggExpression.Method, sourceParameter, aggLambda);
                    }
                    expressions.Add(aggCallExpression);
                    _aggProperties.Add(CreateEdmProperty(aggCallExpression.Type, aggExpression.Alias, false));
                }
                else
                {
                    throw new NotSupportedException("Unknown aggregate expression type " + aggExpressionBase.GetType().Name);
                }
            }

            NewExpression    newExpression    = OeExpressionHelper.CreateTupleExpression(expressions);
            MethodInfo       selectMethodInfo = OeMethodInfoHelper.GetSelectMethodInfo(sourceType, newExpression.Type);
            LambdaExpression lambda           = Expression.Lambda(newExpression, sourceParameter);

            return(Expression.Call(selectMethodInfo, source, lambda));
        }
        private bool CompareAggregate(AggregateTransformationNode node1, AggregateTransformationNode node2)
        {
            if (node1 == node2)
            {
                return(true);
            }
            if (node1 == null || node2 == null)
            {
                return(false);
            }

            return(EnumerableComparer.Compare(node1.Expressions, node2.Expressions, CompareAggregate));
        }
Exemplo n.º 8
0
        public void BindApplyWithCountInAggregateShouldReturnApplyClause()
        {
            IEnumerable <QueryToken> tokens = _parser.ParseApply("aggregate($count as TotalCount)");

            ApplyBinder binder = new ApplyBinder(FakeBindMethods.BindSingleComplexProperty, _bindingState);
            ApplyClause actual = binder.BindApply(tokens);

            Assert.NotNull(actual);
            AggregateTransformationNode aggregate = Assert.IsType <AggregateTransformationNode>(Assert.Single(actual.Transformations));

            Assert.Equal(TransformationNodeKind.Aggregate, aggregate.Kind);
            Assert.NotNull(aggregate.Expressions);
            AggregateExpression statement = Assert.Single(aggregate.Expressions);

            Assert.Equal(AggregationMethod.VirtualPropertyCount, statement.Method);
            Assert.Equal("TotalCount", statement.Alias);
        }
Exemplo n.º 9
0
        public void BindApplyWithEntitySetAggregationWithoutGroupByReturnApplyClause()
        {
            IEnumerable <QueryToken> tokens =
                _parser.ParseApply(
                    "aggregate(MyPaintings(Value with sum as TotalValue))");

            BindingState   state         = new BindingState(_configuration);
            MetadataBinder metadataBiner = new MetadataBinder(_bindingState);

            ApplyBinder binder = new ApplyBinder(metadataBiner.Bind, _bindingState);
            ApplyClause actual = binder.BindApply(tokens);

            Assert.NotNull(actual);
            Assert.NotNull(actual.Transformations);
            AggregateTransformationNode aggregate = Assert.IsType <AggregateTransformationNode>(Assert.Single(actual.Transformations));

            Assert.NotNull(aggregate.AggregateExpressions);
            Assert.IsType <EntitySetAggregateExpression>(Assert.Single(aggregate.AggregateExpressions));
        }
Exemplo n.º 10
0
        public void BindApplyWithAggregateShouldReturnApplyClause()
        {
            IEnumerable <QueryToken> tokens = _parser.ParseApply("aggregate(UnitPrice with sum as TotalPrice)");

            ApplyBinder binder = new ApplyBinder(FakeBindMethods.BindSingleComplexProperty, _bindingState);
            ApplyClause actual = binder.BindApply(tokens);

            Assert.NotNull(actual);
            AggregateTransformationNode aggregate = Assert.IsType <AggregateTransformationNode>(Assert.Single(actual.Transformations));

            Assert.Equal(TransformationNodeKind.Aggregate, aggregate.Kind);
            Assert.NotNull(aggregate.AggregateExpressions);

            AggregateExpression statement = Assert.IsType <AggregateExpression>(Assert.Single(aggregate.AggregateExpressions));

            VerifyIsFakeSingleValueNode(statement.Expression);
            Assert.Equal(AggregationMethod.Sum, statement.Method);
            Assert.Equal("TotalPrice", statement.Alias);
        }
        private void Translate(AggregateTransformationNode transformation)
        {
            bool appendComma = false;

            foreach (AggregateExpression aggExpression in transformation.Expressions)
            {
                appendComma = AppendComma(appendComma);

                if (aggExpression.Method != AggregationMethod.VirtualPropertyCount)
                {
                    AppendExpression(aggExpression.Expression);
                    query.Append(ExpressionConstants.SymbolEscapedSpace);
                    AppendWord(ExpressionConstants.KeywordWith);
                }

                AppendWord(GetAggregationMethodName(aggExpression));
                AppendWord(ExpressionConstants.KeywordAs);
                query.Append(aggExpression.Alias);
            }
        }
Exemplo n.º 12
0
        public void BindVirtualPropertiesAfterCollapseReturnsApplyClause()
        {
            IEnumerable <QueryToken> tokens =
                _parser.ParseApply(
                    "groupby((ID))/aggregate($count as Count)");

            BindingState   state         = new BindingState(_configuration);
            MetadataBinder metadataBiner = new MetadataBinder(_bindingState);

            ApplyBinder binder = new ApplyBinder(metadataBiner.Bind, _bindingState);
            ApplyClause actual = binder.BindApply(tokens);

            Assert.NotNull(actual);
            Assert.Equal(2, actual.Transformations.Count());
            Assert.IsType <GroupByTransformationNode>(actual.Transformations.First());
            AggregateTransformationNode aggregate = Assert.IsType <AggregateTransformationNode>(actual.Transformations.Last());
            AggregateExpression         aggExp    = Assert.IsType <AggregateExpression>(Assert.Single(aggregate.AggregateExpressions));

            Assert.Equal(AggregationMethod.VirtualPropertyCount, aggExp.Method);
        }
Exemplo n.º 13
0
        public void BindApplyWithAverageInAggregateShouldReturnApplyClause()
        {
            IEnumerable <QueryToken> tokens = _parser.ParseApply("aggregate(UnitPrice with average as AveragePrice)");

            ApplyBinder binder = new ApplyBinder(FakeBindMethods.BindMethodReturningASingleFloatPrimitive, _bindingState);
            ApplyClause actual = binder.BindApply(tokens);

            Assert.NotNull(actual);
            AggregateTransformationNode aggregate = Assert.IsType <AggregateTransformationNode>(Assert.Single(actual.Transformations));

            Assert.Equal(TransformationNodeKind.Aggregate, aggregate.Kind);
            Assert.NotNull(aggregate.AggregateExpressions);

            AggregateExpression statement = Assert.IsType <AggregateExpression>(Assert.Single(aggregate.AggregateExpressions));

            Assert.NotNull(statement.Expression);
            Assert.Same(FakeBindMethods.FakeSingleFloatPrimitive, statement.Expression);
            Assert.Equal(AggregationMethod.Average, statement.Method);
            Assert.Equal("AveragePrice", statement.Alias);
        }
Exemplo n.º 14
0
        public void BindApplyWithExpandReturnApplyClause()
        {
            IEnumerable <QueryToken> tokens =
                _parser.ParseApply(
                    "expand(MyPaintings, filter(FrameColor eq 'Red'))/groupby((LifeTime),aggregate(MyPaintings($count as Count)))");

            BindingState   state         = new BindingState(_configuration);
            MetadataBinder metadataBiner = new MetadataBinder(_bindingState);

            ApplyBinder binder = new ApplyBinder(metadataBiner.Bind, _bindingState, V4configuration, new ODataPathInfo(HardCodedTestModel.GetPersonType(), HardCodedTestModel.GetPeopleSet()));
            ApplyClause actual = binder.BindApply(tokens);

            actual.Should().NotBeNull();
            actual.Transformations.Should().HaveCount(2);

            ExpandTransformationNode expand = actual.Transformations.First() as ExpandTransformationNode;

            expand.Should().NotBeNull();
            expand.ExpandClause.Should().NotBeNull();
            expand.ExpandClause.SelectedItems.Should().HaveCount(1);
            ExpandedNavigationSelectItem expandItem = expand.ExpandClause.SelectedItems.First() as ExpandedNavigationSelectItem;

            expandItem.Should().NotBeNull();
            expandItem.NavigationSource.Name.ShouldBeEquivalentTo("Paintings");
            expandItem.FilterOption.Should().NotBeNull();

            GroupByTransformationNode groupBy = actual.Transformations.Last() as GroupByTransformationNode;

            groupBy.Should().NotBeNull();
            groupBy.GroupingProperties.Should().HaveCount(1);

            AggregateTransformationNode aggregate = groupBy.ChildTransformations as AggregateTransformationNode;

            aggregate.Should().NotBeNull();
            aggregate.AggregateExpressions.Should().HaveCount(1);

            EntitySetAggregateExpression entitySetAggregate = aggregate.AggregateExpressions.First() as EntitySetAggregateExpression;

            entitySetAggregate.Should().NotBeNull();
        }
Exemplo n.º 15
0
        public void BindVirtualPropertiesAfterCollapseReturnsApplyClause()
        {
            IEnumerable <QueryToken> tokens =
                _parser.ParseApply(
                    "groupby((ID))/aggregate($count as Count)");

            BindingState   state         = new BindingState(_configuration);
            MetadataBinder metadataBiner = new MetadataBinder(_bindingState);

            ApplyBinder binder = new ApplyBinder(metadataBiner.Bind, _bindingState);
            ApplyClause actual = binder.BindApply(tokens);

            actual.Should().NotBeNull();
            actual.Transformations.Should().HaveCount(2);
            GroupByTransformationNode groupby = actual.Transformations.First() as GroupByTransformationNode;

            groupby.Should().NotBeNull();
            AggregateTransformationNode aggregate = actual.Transformations.Last() as AggregateTransformationNode;

            aggregate.Should().NotBeNull();
            aggregate.AggregateExpressions.Should().HaveCount(1);
            aggregate.AggregateExpressions.Single().As <AggregateExpression>().Method.ShouldBeEquivalentTo(AggregationMethod.VirtualPropertyCount);
        }
Exemplo n.º 16
0
        public void BindApplyWithEntitySetAggregationWithoutGroupByReturnApplyClause()
        {
            IEnumerable <QueryToken> tokens =
                _parser.ParseApply(
                    "aggregate(MyPaintings(Value with sum as TotalValue))");

            BindingState   state         = new BindingState(_configuration);
            MetadataBinder metadataBiner = new MetadataBinder(_bindingState);

            ApplyBinder binder = new ApplyBinder(metadataBiner.Bind, _bindingState);
            ApplyClause actual = binder.BindApply(tokens);

            actual.Should().NotBeNull();
            actual.Transformations.Should().HaveCount(1);

            AggregateTransformationNode aggregate = actual.Transformations.First() as AggregateTransformationNode;

            aggregate.Should().NotBeNull();
            aggregate.AggregateExpressions.Should().HaveCount(1);

            EntitySetAggregateExpression entitySetAggregate = aggregate.AggregateExpressions.First() as EntitySetAggregateExpression;

            entitySetAggregate.Should().NotBeNull();
        }
Exemplo n.º 17
0
        public void BindApplyWithEntitySetAggregationReturnApplyClause()
        {
            IEnumerable <QueryToken> tokens =
                _parser.ParseApply(
                    "groupby((LifeTime),aggregate(MyPaintings($count as Count)))");

            BindingState   state         = new BindingState(_configuration);
            MetadataBinder metadataBiner = new MetadataBinder(_bindingState);

            ApplyBinder binder = new ApplyBinder(metadataBiner.Bind, _bindingState);
            ApplyClause actual = binder.BindApply(tokens);

            Assert.NotNull(actual);
            Assert.NotNull(actual.Transformations);
            GroupByTransformationNode groupBy = Assert.IsType <GroupByTransformationNode>(Assert.Single(actual.Transformations));

            Assert.NotNull(groupBy.GroupingProperties);

            AggregateTransformationNode aggregate = Assert.IsType <AggregateTransformationNode>(groupBy.ChildTransformations);

            Assert.NotNull(aggregate.AggregateExpressions);

            Assert.IsType <EntitySetAggregateExpression>(Assert.Single(aggregate.AggregateExpressions));
        }
Exemplo n.º 18
0
        public void BindApplyWithCountInAggregateShouldReturnApplyClause()
        {
            IEnumerable <QueryToken> tokens = _parser.ParseApply("aggregate($count as TotalCount)");

            ApplyBinder binder = new ApplyBinder(FakeBindMethods.BindSingleComplexProperty, _bindingState);
            ApplyClause actual = binder.BindApply(tokens);

            actual.Should().NotBeNull();
            actual.Transformations.Should().HaveCount(1);

            List <TransformationNode>   transformations = actual.Transformations.ToList();
            AggregateTransformationNode aggregate       = transformations[0] as AggregateTransformationNode;

            aggregate.Should().NotBeNull();
            aggregate.Kind.Should().Be(TransformationNodeKind.Aggregate);
            aggregate.Expressions.Should().NotBeNull();
            aggregate.Expressions.Should().HaveCount(1);

            List <AggregateExpression> statements = aggregate.Expressions.ToList();
            AggregateExpression        statement  = statements[0];

            statement.Method.Should().Be(AggregationMethod.VirtualPropertyCount);
            statement.Alias.Should().Be("TotalCount");
        }
Exemplo n.º 19
0
 private void AddAggregationPropertiesToModel(AggregateTransformationNode aggregationProperties
                                              , EdmEntityTypeSettings sourceEdmSetting
                                              , EdmEntityType edmEntityType
                                              , Dictionary <string, AggregateExpression> aggregatePropList
                                              , EdmEntityTypeSettings targetEdmSetting
                                              , EdmComplexType edmComplexType
                                              , Dictionary <string, object> latestStateDictionary)
 {
     foreach (var aggregationExpression in aggregationProperties.AggregateExpressions)
     {
         var expr = (AggregateExpression)aggregationExpression;
         if (expr.Method != AggregationMethod.Custom)
         {
             bool?  isNullable    = null;
             string propertyAlias = "";
             var    primitiveKind = expr.Expression.TypeReference.PrimitiveKind();
             if (expr.Method == AggregationMethod.VirtualPropertyCount)
             {
                 var sourceProperty = (CountVirtualPropertyNode)expr.Expression;
                 isNullable    = sourceProperty.TypeReference.IsNullable;
                 propertyAlias = !string.IsNullOrWhiteSpace(expr.Alias) ? expr.Alias : sourceProperty.Kind.ToString();
                 primitiveKind = EdmPrimitiveTypeKind.Int32;
             }
             else
             {
                 var sourceProperty    = (SingleValuePropertyAccessNode)expr.Expression;
                 var sourceEdmProperty = sourceEdmSetting.Properties.FirstOrDefault(predicate => predicate.PropertyName.Equals(sourceProperty.Property.Name));
                 isNullable    = sourceEdmProperty.IsNullable;
                 propertyAlias = !string.IsNullOrWhiteSpace(expr.Alias) ? expr.Alias : sourceProperty.Property.Name;
                 if (expr.Method == AggregationMethod.Average)
                 {
                     primitiveKind = EdmPrimitiveTypeKind.Double;
                 }
                 if (expr.Method == AggregationMethod.CountDistinct)
                 {
                     primitiveKind = EdmPrimitiveTypeKind.Int32;
                 }
             }
             edmEntityType.AddStructuralProperty(propertyAlias, primitiveKind);
             aggregatePropList.Add(propertyAlias, expr);
             targetEdmSetting.Properties.Add(new EdmEntityTypePropertySetting
             {
                 PropertyName = propertyAlias,
                 PropertyType = GetStringTypeFromEdmPrimitiveType(primitiveKind),
                 IsNullable   = isNullable
             });
         }
         else
         {
             //Create a list of source type
             if (expr.MethodDefinition.MethodLabel.Contains(ODataFilterConstants.AggregationMethod_Custom_List, StringComparison.OrdinalIgnoreCase))
             {
                 foreach (var property in sourceEdmSetting.Properties)
                 {
                     edmComplexType.AddStructuralProperty(property.PropertyName, property.GetEdmPrimitiveTypeKind());
                 }
                 var groupItemsPropertyName = !string.IsNullOrWhiteSpace(expr.Alias) ? expr.Alias : "Items";
                 var complexTypeReference   = new EdmComplexTypeReference(edmComplexType, true);
                 edmEntityType.AddStructuralProperty(groupItemsPropertyName, new EdmCollectionTypeReference(new EdmCollectionType(complexTypeReference)));
                 aggregatePropList.Add(groupItemsPropertyName, expr);
                 targetEdmSetting.Properties.Add(new EdmEntityTypePropertySetting
                 {
                     PropertyName = groupItemsPropertyName,
                     PropertyType = "List",
                     IsNullable   = null
                 });
                 latestStateDictionary.Add(RequestFilterConstants.GetComplexTypeKeyName(ApplyParser, StepIndex), edmComplexType);
             }
             else if (expr.MethodDefinition.MethodLabel.Contains(ODataFilterConstants.AggregationMethod_Custom_CountDistinct, StringComparison.OrdinalIgnoreCase) ||
                      expr.MethodDefinition.MethodLabel.Contains(ODataFilterConstants.AggregationMethod_Custom_Count, StringComparison.OrdinalIgnoreCase))
             {
                 var sourceProperty        = (SingleValuePropertyAccessNode)expr.Expression;
                 var primitiveKind         = EdmPrimitiveTypeKind.Int32;
                 var countDistinctPropName = !string.IsNullOrWhiteSpace(expr.Alias) ? expr.Alias : sourceProperty.Property.Name;
                 edmEntityType.AddStructuralProperty(countDistinctPropName, primitiveKind);
                 aggregatePropList.Add(countDistinctPropName, expr);
                 targetEdmSetting.Properties.Add(new EdmEntityTypePropertySetting
                 {
                     PropertyName = countDistinctPropName,
                     PropertyType = GetStringTypeFromEdmPrimitiveType(primitiveKind),
                     IsNullable   = null
                 });
             }
             else
             {
                 throw new FeatureNotSupportedException($"{ApplyParser}-Custom Aggregation-{expr.MethodDefinition.MethodLabel}", "Invalid Custom Aggregation");
             }
         }
     }
 }
 private void Translate(AggregateTransformationNode transformation)
 {
     Translate(transformation.AggregateExpressions);
 }