public MethodCallExpression Build(IEdmModel edmModel, Expression outerSource, Expression innerSource,
                                          IReadOnlyList <IEdmNavigationProperty> joinPath, IEdmNavigationProperty navigationProperty)
        {
            if (navigationProperty.ContainsTarget)
            {
                ModelBuilder.ManyToManyJoinDescription joinDescription = edmModel.GetManyToManyJoinDescription(navigationProperty);
                IEdmEntitySet joinEntitySet = OeEdmClrHelper.GetEntitySet(edmModel, joinDescription.JoinNavigationProperty);
                Expression    joinSource    = OeEnumerableStub.CreateEnumerableStubExpression(joinDescription.JoinClassType, joinEntitySet);

                outerSource = Build(outerSource, joinSource, joinPath, joinDescription.JoinNavigationProperty, false);
                AddJoinPath(joinPath, joinDescription.JoinNavigationProperty);

                var fixedJoinPath = new IEdmNavigationProperty[joinPath.Count + 1];
                for (int i = 0; i < joinPath.Count; i++)
                {
                    fixedJoinPath[i] = joinPath[i];
                }
                fixedJoinPath[fixedJoinPath.Length - 1] = joinDescription.JoinNavigationProperty;

                outerSource = Build(outerSource, innerSource, fixedJoinPath, joinDescription.TargetNavigationProperty, true);
                _joinPaths.RemoveAt(_joinPaths.Count - 1);
            }
            else
            {
                outerSource = Build(outerSource, innerSource, joinPath, navigationProperty, false);
            }

            AddJoinPath(joinPath, navigationProperty);
            return((MethodCallExpression)outerSource);
        }
示例#2
0
        public MethodCallExpression Build(Expression outerSource, Expression innerSource, IReadOnlyList <IEdmNavigationProperty> joinPath, IEdmNavigationProperty navigationProperty)
        {
            if (navigationProperty.ContainsTarget)
            {
                ModelBuilder.ManyToManyJoinDescription joinDescription = Visitor.EdmModel.GetManyToManyJoinClassType(navigationProperty);
                Expression joinSource = Expression.Constant(null, typeof(IEnumerable <>).MakeGenericType(joinDescription.JoinClassType));
                outerSource = Build(outerSource, joinSource, joinPath, joinDescription.JoinNavigationProperty, false);
                AddJoinPath(joinPath, joinDescription.JoinNavigationProperty);

                var fixedJoinPath = new IEdmNavigationProperty[joinPath.Count + 1];
                for (int i = 0; i < joinPath.Count; i++)
                {
                    fixedJoinPath[i] = joinPath[i];
                }
                fixedJoinPath[fixedJoinPath.Length - 1] = joinDescription.JoinNavigationProperty;

                outerSource = Build(outerSource, innerSource, fixedJoinPath, joinDescription.TargetNavigationProperty, true);
                _joinPaths.RemoveAt(_joinPaths.Count - 1);
            }
            else
            {
                outerSource = Build(outerSource, innerSource, joinPath, navigationProperty, false);
            }

            AddJoinPath(joinPath, navigationProperty);
            return((MethodCallExpression)outerSource);
        }
示例#3
0
        private static IReadOnlyList <IEdmNavigationProperty> GetFixedManyToManyPath(IEdmModel edmModel, IReadOnlyList <IEdmNavigationProperty> joinPath)
        {
            List <IEdmNavigationProperty> fixedJoinPath = null;

            for (int i = 0; i < joinPath.Count; i++)
            {
                if (joinPath[i].ContainsTarget)
                {
                    fixedJoinPath = new List <IEdmNavigationProperty>(joinPath.Count + 1);
                    break;
                }
            }
            if (fixedJoinPath == null)
            {
                return(joinPath);
            }

            for (int i = 0; i < joinPath.Count; i++)
            {
                if (joinPath[i].ContainsTarget)
                {
                    ModelBuilder.ManyToManyJoinDescription joinDescription = edmModel.GetManyToManyJoinClassType(joinPath[i]);
                    fixedJoinPath.Add(joinDescription.JoinNavigationProperty);
                    fixedJoinPath.Add(joinDescription.TargetNavigationProperty);
                }
                else
                {
                    fixedJoinPath.Add(joinPath[i]);
                }
            }
            return(fixedJoinPath);
        }
示例#4
0
        public MethodCallExpression Build(Expression outer, Expression inner, ODataPath odataPath, OrderByClause orderBy, long?skip, long?top)
        {
            var segment = (NavigationPropertySegment)odataPath.LastSegment;
            IEdmNavigationProperty navigationProperty = segment.NavigationProperty;

            if (navigationProperty.ContainsTarget)
            {
                ModelBuilder.ManyToManyJoinDescription joinDescription = _edmModel.GetManyToManyJoinDescription(navigationProperty);
                IEdmEntitySet joinEntitySet = OeEdmClrHelper.GetEntitySet(_edmModel, joinDescription.JoinNavigationProperty);
                outer = OeEnumerableStub.CreateEnumerableStubExpression(joinDescription.JoinClassType, joinEntitySet);
                navigationProperty = joinDescription.TargetNavigationProperty;
            }

            Type outerType = OeExpressionHelper.GetCollectionItemType(outer.Type);
            ParameterExpression outerParameter = Expression.Parameter(outerType, outerType.Name);

            inner = new ReplaceParameterVisitor(outerParameter).Visit(inner); //replace $it
            Expression subquery = CreateWhereExpression(outerParameter, inner, navigationProperty);

            subquery = _expressionBuilder.ApplyOrderBy(subquery, orderBy);
            subquery = _expressionBuilder.ApplySkip(subquery, skip, odataPath);
            subquery = _expressionBuilder.ApplyTake(subquery, top, odataPath);

            Type       innerType            = OeExpressionHelper.GetCollectionItemType(inner.Type);
            MethodInfo selectManyMethdoInfo = OeMethodInfoHelper.GetSelectManyMethodInfo(outerType, innerType);

            return(Expression.Call(selectManyMethdoInfo, outer, Expression.Lambda(subquery, outerParameter)));
        }
示例#5
0
        private Expression GetInnerSource(OeSelectItem navigationItem, ExpandedNavigationSelectItem item)
        {
            Type         clrEntityType         = _visitor.EdmModel.GetClrType(navigationItem.EdmProperty.DeclaringType);
            PropertyInfo navigationClrProperty = clrEntityType.GetPropertyIgnoreCase(navigationItem.EdmProperty);

            Type itemType = OeExpressionHelper.GetCollectionItemType(navigationClrProperty.PropertyType);

            if (itemType == null)
            {
                itemType = navigationClrProperty.PropertyType;
            }

            var visitor           = new OeQueryNodeVisitor(_visitor, Expression.Parameter(itemType));
            var expressionBuilder = new OeExpressionBuilder(_joinBuilder, visitor);

            var navigationEdmProperty = (IEdmNavigationProperty)navigationItem.EdmProperty;

            if (navigationEdmProperty.ContainsTarget)
            {
                ModelBuilder.ManyToManyJoinDescription joinDescription = _visitor.EdmModel.GetManyToManyJoinDescription(navigationEdmProperty);
                navigationEdmProperty = joinDescription.TargetNavigationProperty;
            }
            IEdmEntitySet innerEntitySet = OeEdmClrHelper.GetEntitySet(_visitor.EdmModel, navigationEdmProperty);
            Expression    innerSource    = OeEnumerableStub.CreateEnumerableStubExpression(itemType, innerEntitySet);

            innerSource = expressionBuilder.ApplyFilter(innerSource, item.FilterOption);
            if (item.SkipOption != null || item.TopOption != null)
            {
                Expression source = OeEnumerableStub.CreateEnumerableStubExpression(navigationClrProperty.DeclaringType, (IEdmEntitySet)_navigationItem.EntitySet);
                innerSource = OeCrossApplyBuilder.Build(source, innerSource, item, navigationItem.Path, expressionBuilder);
            }

            return(innerSource);
        }
        private Expression GetInnerSource(OeNavigationSelectItem navigationItem)
        {
            if (navigationItem.Parent == null)
            {
                throw new InvalidOperationException("Inner source cannot exist for root item");
            }

            Type         clrEntityType         = _edmModel.GetClrType(navigationItem.EdmProperty.DeclaringType);
            PropertyInfo navigationClrProperty = clrEntityType.GetPropertyIgnoreCase(navigationItem.EdmProperty);

            Type itemType          = OeExpressionHelper.GetCollectionItemTypeOrNull(navigationClrProperty.PropertyType) ?? navigationClrProperty.PropertyType;
            var  visitor           = new OeQueryNodeVisitor(_joinBuilder.Visitor, Expression.Parameter(itemType));
            var  expressionBuilder = new OeExpressionBuilder(_joinBuilder, visitor);

            IEdmNavigationProperty navigationProperty = navigationItem.EdmProperty;

            if (navigationItem.EdmProperty.ContainsTarget)
            {
                ModelBuilder.ManyToManyJoinDescription joinDescription = _edmModel.GetManyToManyJoinDescription(navigationProperty);
                navigationProperty = joinDescription.TargetNavigationProperty;
            }
            IEdmEntitySet innerEntitySet = OeEdmClrHelper.GetEntitySet(_edmModel, navigationProperty);
            Expression    innerSource    = OeEnumerableStub.CreateEnumerableStubExpression(itemType, innerEntitySet);

            ExpandedNavigationSelectItem item = navigationItem.NavigationSelectItem;

            innerSource = expressionBuilder.ApplyFilter(innerSource, item.FilterOption);

            long?top = GetTop(navigationItem, item.TopOption);

            if (top == null && item.SkipOption == null)
            {
                return(innerSource);
            }

            OrderByClause orderByClause = item.OrderByOption;

            if (navigationItem.PageSize > 0)
            {
                orderByClause = OeSkipTokenParser.GetUniqueOrderBy(navigationItem.EntitySet, item.OrderByOption, null);
            }

            var        entitySet = (IEdmEntitySet)navigationItem.Parent.EntitySet;
            Expression source    = OeEnumerableStub.CreateEnumerableStubExpression(navigationClrProperty.DeclaringType, entitySet);

            var crossApplyBuilder = new OeCrossApplyBuilder(_edmModel, expressionBuilder);

            return(crossApplyBuilder.Build(source, innerSource, navigationItem.Path, orderByClause, item.SkipOption, top));
        }
示例#7
0
        private SelectExpandClause BuildSelectExpandClause(IEdmEntitySet entitySet, GraphQLSelectionSet selectionSet)
        {
            var selectItems = new List <SelectItem>();

            foreach (ASTNode astNode in selectionSet.Selections)
            {
                if (astNode is GraphQLFieldSelection fieldSelection)
                {
                    IEdmProperty edmProperty = FindEdmProperty(entitySet.EntityType(), fieldSelection.Name.Value);
                    if (fieldSelection.SelectionSet == null)
                    {
                        var structuralProperty = (IEdmStructuralProperty)edmProperty;
                        selectItems.Add(new PathSelectItem(new ODataSelectPath(new PropertySegment(structuralProperty))));
                    }
                    else
                    {
                        var           navigationProperty = (IEdmNavigationProperty)edmProperty;
                        IEdmEntitySet parentEntitySet;
                        if (navigationProperty.ContainsTarget)
                        {
                            ModelBuilder.ManyToManyJoinDescription joinDescription = _edmModel.GetManyToManyJoinDescription(navigationProperty);
                            parentEntitySet = OeEdmClrHelper.GetEntitySet(_edmModel, joinDescription.TargetNavigationProperty);
                        }
                        else
                        {
                            parentEntitySet = OeEdmClrHelper.GetEntitySet(_edmModel, navigationProperty);
                        }

                        var expandPath = new ODataExpandPath(new NavigationPropertySegment(navigationProperty, parentEntitySet));

                        FilterClause filterOption = null;
                        if (fieldSelection.Arguments.Any())
                        {
                            filterOption = BuildFilterClause(parentEntitySet, fieldSelection);
                        }

                        SelectExpandClause childSelectExpand = BuildSelectExpandClause(parentEntitySet, fieldSelection.SelectionSet);
                        var expandedSelectItem = new ExpandedNavigationSelectItem(expandPath, parentEntitySet, childSelectExpand, filterOption, null, null, null, null, null, null);
                        selectItems.Add(expandedSelectItem);
                    }
                }
                else
                {
                    throw new NotSupportedException("selection " + astNode.GetType().Name + " not supported");
                }
            }

            return(new SelectExpandClause(selectItems, false));
        }
示例#8
0
        private static FilterClause?GetFilter(IEdmModel edmModel, OeEntryFactory entryFactory, ExpandedNavigationSelectItem item, Object value)
        {
            SingleValueNode filterExpression;
            ResourceRangeVariableReferenceNode refNode;

            var segment = (NavigationPropertySegment)item.PathToNavigationProperty.LastSegment;
            IEdmNavigationProperty navigationProperty = segment.NavigationProperty;

            if (navigationProperty.ContainsTarget)
            {
                ModelBuilder.ManyToManyJoinDescription joinDescription = edmModel.GetManyToManyJoinDescription(navigationProperty);
                navigationProperty = joinDescription.JoinNavigationProperty.Partner;

                IEdmEntitySet joinNavigationSource             = OeEdmClrHelper.GetEntitySet(edmModel, joinDescription.JoinNavigationProperty);
                ResourceRangeVariableReferenceNode joinRefNode = OeEdmClrHelper.CreateRangeVariableReferenceNode(joinNavigationSource, "d");

                IEdmEntitySet targetNavigationSource             = OeEdmClrHelper.GetEntitySet(edmModel, joinDescription.TargetNavigationProperty);
                ResourceRangeVariableReferenceNode targetRefNode = OeEdmClrHelper.CreateRangeVariableReferenceNode(targetNavigationSource);

                var anyNode = new AnyNode(new Collection <RangeVariable>()
                {
                    joinRefNode.RangeVariable, targetRefNode.RangeVariable
                }, joinRefNode.RangeVariable)
                {
                    Source = new CollectionNavigationNode(targetRefNode, joinDescription.TargetNavigationProperty.Partner, null),
                    Body   = OeExpressionHelper.CreateFilterExpression(joinRefNode, GetKeys(navigationProperty.PrincipalProperties(), navigationProperty.DependentProperties()))
                };

                refNode          = targetRefNode;
                filterExpression = anyNode;
            }
            else
            {
                IEnumerable <IEdmStructuralProperty> parentKeys;
                IEnumerable <IEdmStructuralProperty> childKeys;
                if (navigationProperty.IsPrincipal())
                {
                    parentKeys = navigationProperty.Partner.PrincipalProperties();
                    childKeys  = navigationProperty.Partner.DependentProperties();
                }
                else
                {
                    if (navigationProperty.Type.IsCollection())
                    {
                        parentKeys = navigationProperty.PrincipalProperties();
                        childKeys  = navigationProperty.DependentProperties();
                    }
                    else
                    {
                        parentKeys = navigationProperty.DependentProperties();
                        childKeys  = navigationProperty.PrincipalProperties();
                    }
                }

                refNode = OeEdmClrHelper.CreateRangeVariableReferenceNode((IEdmEntitySetBase)segment.NavigationSource);
                List <KeyValuePair <IEdmStructuralProperty, Object> > keys = GetKeys(parentKeys, childKeys);
                if (IsNullKeys(keys))
                {
                    return(null);
                }

                filterExpression = OeExpressionHelper.CreateFilterExpression(refNode, keys);
            }

            if (item.FilterOption != null)
            {
                filterExpression = new BinaryOperatorNode(BinaryOperatorKind.And, filterExpression, item.FilterOption.Expression);
            }

            return(new FilterClause(filterExpression, refNode.RangeVariable));

            List <KeyValuePair <IEdmStructuralProperty, Object> > GetKeys(IEnumerable <IEdmStructuralProperty> parentKeys, IEnumerable <IEdmStructuralProperty> childKeys)
            {
                var keys = new List <KeyValuePair <IEdmStructuralProperty, Object> >();
                IEnumerator <IEdmStructuralProperty> childKeyEnumerator = childKeys.GetEnumerator();

                foreach (IEdmStructuralProperty parentKey in parentKeys)
                {
                    childKeyEnumerator.MoveNext();
                    Object keyValue = entryFactory.GetAccessorByName(parentKey.Name).GetValue(value);
                    keys.Add(new KeyValuePair <IEdmStructuralProperty, Object>(childKeyEnumerator.Current, keyValue));
                }
                return(keys);
            }
示例#9
0
            private static Uri BuildNavigationNextPageLink(IEdmModel edmModel, OeEntryFactory entryFactory, ExpandedNavigationSelectItem expandedNavigationSelectItem, Object value)
            {
                SingleValueNode filterExpression;
                ResourceRangeVariableReferenceNode refNode;

                var segment = (NavigationPropertySegment)expandedNavigationSelectItem.PathToNavigationProperty.LastSegment;
                IEdmNavigationProperty navigationProperty = segment.NavigationProperty;

                if (navigationProperty.ContainsTarget)
                {
                    ModelBuilder.ManyToManyJoinDescription joinDescription = edmModel.GetManyToManyJoinDescription(navigationProperty);
                    navigationProperty = joinDescription.JoinNavigationProperty.Partner;

                    IEdmEntitySet joinNavigationSource             = OeEdmClrHelper.GetEntitySet(edmModel, joinDescription.JoinNavigationProperty);
                    ResourceRangeVariableReferenceNode joinRefNode = OeEdmClrHelper.CreateRangeVariableReferenceNode(joinNavigationSource, "d");

                    IEdmEntitySet targetNavigationSource             = OeEdmClrHelper.GetEntitySet(edmModel, joinDescription.TargetNavigationProperty);
                    ResourceRangeVariableReferenceNode targetRefNode = OeEdmClrHelper.CreateRangeVariableReferenceNode(targetNavigationSource);

                    var anyNode = new AnyNode(new Collection <RangeVariable>()
                    {
                        joinRefNode.RangeVariable, targetRefNode.RangeVariable
                    }, joinRefNode.RangeVariable)
                    {
                        Source = new CollectionNavigationNode(targetRefNode, joinDescription.TargetNavigationProperty.Partner, null),
                        Body   = OeGetParser.CreateFilterExpression(joinRefNode, GetKeys(navigationProperty))
                    };

                    refNode          = targetRefNode;
                    filterExpression = anyNode;
                }
                else
                {
                    if (navigationProperty.IsPrincipal())
                    {
                        navigationProperty = navigationProperty.Partner;
                    }

                    refNode          = OeEdmClrHelper.CreateRangeVariableReferenceNode((IEdmEntitySetBase)segment.NavigationSource);
                    filterExpression = OeGetParser.CreateFilterExpression(refNode, GetKeys(navigationProperty));
                }

                if (expandedNavigationSelectItem.FilterOption != null)
                {
                    filterExpression = new BinaryOperatorNode(BinaryOperatorKind.And, filterExpression, expandedNavigationSelectItem.FilterOption.Expression);
                }

                var pathSegments = new ODataPathSegment[] { new EntitySetSegment((IEdmEntitySet)refNode.NavigationSource) };
                var odataUri     = new ODataUri()
                {
                    Path            = new ODataPath(pathSegments),
                    Filter          = new FilterClause(filterExpression, refNode.RangeVariable),
                    OrderBy         = expandedNavigationSelectItem.OrderByOption,
                    SelectAndExpand = expandedNavigationSelectItem.SelectAndExpand,
                    Top             = expandedNavigationSelectItem.TopOption,
                    Skip            = expandedNavigationSelectItem.SkipOption,
                    QueryCount      = expandedNavigationSelectItem.CountOption
                };

                return(odataUri.BuildUri(ODataUrlKeyDelimiter.Parentheses));

                List <KeyValuePair <IEdmStructuralProperty, Object> > GetKeys(IEdmNavigationProperty edmNavigationProperty)
                {
                    var keys = new List <KeyValuePair <IEdmStructuralProperty, Object> >();
                    IEnumerator <IEdmStructuralProperty> dependentProperties = edmNavigationProperty.DependentProperties().GetEnumerator();

                    foreach (IEdmStructuralProperty key in edmNavigationProperty.PrincipalProperties())
                    {
                        dependentProperties.MoveNext();
                        Object keyValue = entryFactory.GetAccessorByName(key.Name).GetValue(value);
                        keys.Add(new KeyValuePair <IEdmStructuralProperty, Object>(dependentProperties.Current, keyValue));
                    }
                    return(keys);
                }
            }