Example #1
0
        private void Translate(OeNavigationSelectItem parentNavigationItem, ExpandedNavigationSelectItem item)
        {
            IEdmEntitySetBase entitySet = OeEdmClrHelper.GetEntitySet(_edmModel, item);

            OeNavigationSelectItemKind kind;

            if (_notSelected)
            {
                kind = OeNavigationSelectItemKind.NotSelected;
            }
            else if (item.SelectAndExpand.IsNextLink())
            {
                kind = OeNavigationSelectItemKind.NextLink;
            }
            else
            {
                kind = OeNavigationSelectItemKind.Normal;
            }

            var childNavigationSelectItem = new OeNavigationSelectItem(entitySet, parentNavigationItem, item, kind);

            childNavigationSelectItem = parentNavigationItem.AddOrGetNavigationItem(childNavigationSelectItem);
            if (childNavigationSelectItem.Kind == OeNavigationSelectItemKind.NextLink)
            {
                return;
            }

            foreach (SelectItem selectItemClause in item.SelectAndExpand.SelectedItems)
            {
                Translate(childNavigationSelectItem, selectItemClause);
            }
        }
Example #2
0
 public OeSelectTranslator(IEdmModel edmModel, OeJoinBuilder joinBuilder, ODataUri odataUri)
 {
     _edmModel           = edmModel;
     _joinBuilder        = joinBuilder;
     _odataUri           = odataUri;
     _rootNavigationItem = new OeNavigationSelectItem(odataUri);
 }
Example #3
0
        private static OePropertyAccessor[] GetAccessors(Type clrEntityType, OeNavigationSelectItem navigationItem)
        {
            ParameterExpression parameter;
            UnaryExpression     typedAccessorParameter;
            IReadOnlyList <MemberExpression> propertyExpressions;

            if (navigationItem.AllSelected)
            {
                if (navigationItem.Parent != null && navigationItem.NavigationSelectItem is ExpandedCountSelectItem)
                {
                    parameter = Expression.Parameter(typeof(Object));
                    typedAccessorParameter = Expression.Convert(parameter, clrEntityType);
                    propertyExpressions    = OeExpressionHelper.GetPropertyExpressions(typedAccessorParameter);
                    return(new[] { OePropertyAccessor.CreatePropertyAccessor(OeEdmClrHelper.CountProperty, propertyExpressions[0], parameter, false) });
                }
                else
                {
                    return(OePropertyAccessor.CreateFromType(clrEntityType, navigationItem.EntitySet));
                }
            }

            parameter = Expression.Parameter(typeof(Object));
            typedAccessorParameter = Expression.Convert(parameter, clrEntityType);
            propertyExpressions    = OeExpressionHelper.GetPropertyExpressions(typedAccessorParameter);

            IReadOnlyList <OeStructuralSelectItem> structuralItems = navigationItem.GetStructuralItemsWithNotSelected();
            var accessors = new OePropertyAccessor[structuralItems.Count];

            for (int i = 0; i < structuralItems.Count; i++)
            {
                accessors[i] = OePropertyAccessor.CreatePropertyAccessor(structuralItems[i].EdmProperty, propertyExpressions[i], parameter, structuralItems[i].NotSelected);
            }

            return(accessors);
        }
Example #4
0
 public OeNavigationSelectItem(IEdmEntitySetBase entitySet, OeNavigationSelectItem parent, ExpandedReferenceSelectItem item, OeNavigationSelectItemKind kind)
     : this(entitySet, CreatePath(parent.Path, item.PathToNavigationProperty))
 {
     _edmProperty          = ((NavigationPropertySegment)item.PathToNavigationProperty.LastSegment).NavigationProperty;
     _navigationSelectItem = item;
     EntitySet             = entitySet;
     Kind   = kind;
     Parent = parent;
 }
        private static long?GetTop(OeNavigationSelectItem navigationItem, long?top)
        {
            if (navigationItem.PageSize > 0 && (top == null || navigationItem.PageSize < top.GetValueOrDefault()))
            {
                top = navigationItem.PageSize;
            }

            return(top);
        }
Example #6
0
        public IReadOnlyList <IEdmNavigationProperty> GetJoinPath()
        {
            var joinPath = new List <IEdmNavigationProperty>();

            for (OeNavigationSelectItem navigationItem = this; navigationItem.Parent != null; navigationItem = navigationItem.Parent)
            {
                joinPath.Insert(0, navigationItem.EdmProperty !);
            }
            return(joinPath);
        }
        private void BuildOrderBySkipTake(OeNavigationSelectItem navigationItem, OrderByClause orderByClause, bool hasSelectItems)
        {
            while (orderByClause != null)
            {
                var propertyNode = (SingleValuePropertyAccessNode)orderByClause.Expression;
                if (propertyNode.Source is SingleNavigationNode navigationNode)
                {
                    OeNavigationSelectItem       match;
                    ExpandedNavigationSelectItem navigationSelectItem = null;
                    do
                    {
                        if ((match = navigationItem.FindHierarchyNavigationItem(navigationNode.NavigationProperty)) != null)
                        {
                            match.AddStructuralItem((IEdmStructuralProperty)propertyNode.Property, true);
                            break;
                        }

                        SelectExpandClause selectExpandClause;
                        if (navigationSelectItem == null)
                        {
                            var pathSelectItem = new PathSelectItem(new ODataSelectPath(new PropertySegment((IEdmStructuralProperty)propertyNode.Property)));
                            selectExpandClause = new SelectExpandClause(new[] { pathSelectItem }, false);
                        }
                        else
                        {
                            selectExpandClause = new SelectExpandClause(new[] { navigationSelectItem }, false);
                        }

                        var segment = new NavigationPropertySegment(navigationNode.NavigationProperty, navigationNode.NavigationSource);
                        navigationSelectItem = new ExpandedNavigationSelectItem(new ODataExpandPath(segment), navigationNode.NavigationSource, selectExpandClause);
                    }while ((navigationNode = navigationNode.Source as SingleNavigationNode) != null);

                    if (navigationSelectItem != null)
                    {
                        if (match == null)
                        {
                            match = navigationItem;
                        }

                        var selectItemTranslator = new OeSelectItemTranslator(_edmModel, true);
                        selectItemTranslator.Translate(match, navigationSelectItem);
                    }
                }
                else
                {
                    if (hasSelectItems)
                    {
                        navigationItem.AddStructuralItem((IEdmStructuralProperty)propertyNode.Property, true);
                    }
                }

                orderByClause = orderByClause.ThenBy;
            }
        }
        private static void Translate(OeNavigationSelectItem parentNavigationItem, OePageSelectItem pageSelectItem)
        {
            if (parentNavigationItem.Parent != null)
            {
                var segment = (NavigationPropertySegment)parentNavigationItem.NavigationSelectItem.PathToNavigationProperty.LastSegment;
                if (!segment.NavigationProperty.Type.IsCollection())
                {
                    return;
                }
            }

            parentNavigationItem.PageSize = pageSelectItem.PageSize;
        }
Example #9
0
        private static OeNavigationEntryFactory[] GetNestedNavigationLinks(OeNavigationSelectItem navigationItem)
        {
            var nestedEntryFactories = new List <OeNavigationEntryFactory>(navigationItem.NavigationItems.Count);

            for (int i = 0; i < navigationItem.NavigationItems.Count; i++)
            {
                if (navigationItem.NavigationItems[i].Kind != OeNavigationSelectItemKind.NotSelected)
                {
                    nestedEntryFactories.Add((OeNavigationEntryFactory)navigationItem.NavigationItems[i].EntryFactory);
                }
            }
            return(nestedEntryFactories.ToArray());
        }
Example #10
0
        private OeNavigationSelectItem AddOrGetNavigationItem(OeNavigationSelectItem parentNavigationItem, ExpandedReferenceSelectItem item, bool isExpand)
        {
            IEdmEntitySetBase entitySet = OeEdmClrHelper.GetEntitySet(_edmModel, item);

            OeNavigationSelectItemKind kind;

            if (_notSelected)
            {
                kind = OeNavigationSelectItemKind.NotSelected;
            }
            else if (item is ExpandedNavigationSelectItem expanded && expanded.SelectAndExpand.IsNextLink())
            {
                kind = OeNavigationSelectItemKind.NextLink;
            }
        private void Translate(OeNavigationSelectItem parentNavigationItem, ExpandedNavigationSelectItem item)
        {
            OeNavigationSelectItem childNavigationSelectItem = AddOrGetNavigationItem(parentNavigationItem, item, true);

            if (childNavigationSelectItem.Kind == OeNavigationSelectItemKind.NextLink)
            {
                return;
            }

            foreach (SelectItem selectItemClause in item.SelectAndExpand.SelectedItems)
            {
                Translate(childNavigationSelectItem, selectItemClause);
            }
        }
        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));
        }
Example #13
0
        public OeNavigationSelectItem(IEdmEntitySetBase entitySet, OeNavigationSelectItem parent, ExpandedNavigationSelectItem item, OeNavigationSelectItemKind kind) : this()
        {
            var segment = (NavigationPropertySegment)item.PathToNavigationProperty.LastSegment;

            var segments = new List <ODataPathSegment>(parent.Path);

            segments.AddRange(item.PathToNavigationProperty);

            EdmProperty          = segment.NavigationProperty;
            EntitySet            = entitySet;
            Kind                 = kind;
            NavigationSelectItem = item;
            Parent               = parent;
            Path                 = new ODataPath(segments);
        }
Example #14
0
        public OeNavigationSelectItem FindHierarchyNavigationItem(IEdmNavigationProperty navigationProperty)
        {
            if (EdmProperty == navigationProperty)
            {
                return(this);
            }

            for (int i = 0; i < _navigationItems.Count; i++)
            {
                OeNavigationSelectItem matched = _navigationItems[i].FindHierarchyNavigationItem(navigationProperty);
                if (matched != null)
                {
                    return(matched);
                }
            }
            return(null);
        }
Example #15
0
        internal OeNavigationSelectItem AddOrGetNavigationItem(OeNavigationSelectItem navigationItem, bool isExpand)
        {
            _allSelected &= isExpand;
            OeNavigationSelectItem?existingNavigationItem = FindChildrenNavigationItem(navigationItem.EdmProperty);

            if (existingNavigationItem == null)
            {
                _navigationItems.Add(navigationItem);
                return(navigationItem);
            }

            if (existingNavigationItem.Kind == OeNavigationSelectItemKind.NotSelected && navigationItem.Kind == OeNavigationSelectItemKind.Normal)
            {
                existingNavigationItem.Kind = OeNavigationSelectItemKind.Normal;
            }

            return(existingNavigationItem);
        }
 public void Translate(OeNavigationSelectItem parentNavigationItem, SelectItem item)
 {
     if (item is ExpandedNavigationSelectItem expandedNavigationSelectItem)
     {
         Translate(parentNavigationItem, expandedNavigationSelectItem);
     }
     else if (item is PathSelectItem pathSelectItem)
     {
         Translate(parentNavigationItem, pathSelectItem);
     }
     else if (item is OePageSelectItem pageSelectItem)
     {
         Translate(parentNavigationItem, pageSelectItem);
     }
     else
     {
         throw new InvalidOperationException("Unknown SelectItem type " + item.GetType().Name);
     }
 }
Example #17
0
        internal OeNavigationSelectItem AddOrGetNavigationItem(OeNavigationSelectItem navigationItem)
        {
            OeNavigationSelectItem existingNavigationItem = FindChildrenNavigationItem(navigationItem.EdmProperty);

            if (existingNavigationItem == null)
            {
                _navigationItems.Add(navigationItem);
                return(navigationItem);
            }

            if (existingNavigationItem.Kind == OeNavigationSelectItemKind.NotSelected && navigationItem.Kind == OeNavigationSelectItemKind.Normal)
            {
                existingNavigationItem.Kind = OeNavigationSelectItemKind.Normal;
            }
            else if (existingNavigationItem.StructuralItems.Count == 0)
            {
                existingNavigationItem._selectAll = true;
            }

            return(existingNavigationItem);
        }
        private static OePropertyAccessor[] GetAccessors(Type clrEntityType, OeNavigationSelectItem navigationItem)
        {
            if (navigationItem.StructuralItems.Count == 0)
            {
                return(OePropertyAccessor.CreateFromType(clrEntityType, navigationItem.EntitySet));
            }

            IReadOnlyList <OeStructuralSelectItem> structuralItems = navigationItem.GetStructuralItemsWithNotSelected();
            var accessors = new OePropertyAccessor[structuralItems.Count];

            ParameterExpression parameter = Expression.Parameter(typeof(Object));
            UnaryExpression     typedAccessorParameter           = Expression.Convert(parameter, clrEntityType);
            IReadOnlyList <MemberExpression> propertyExpressions = OeExpressionHelper.GetPropertyExpressions(typedAccessorParameter);

            for (int i = 0; i < structuralItems.Count; i++)
            {
                accessors[i] = OePropertyAccessor.CreatePropertyAccessor(structuralItems[i].EdmProperty, propertyExpressions[i], parameter, structuralItems[i].NotSelected);
            }

            return(accessors);
        }
        private void Translate(OeNavigationSelectItem parentNavigationItem, PathSelectItem item)
        {
            if (item.SelectedPath.LastSegment is NavigationPropertySegment navigationSegment)
            {
                IEdmNavigationSource navigationSource = navigationSegment.NavigationSource;
                if (navigationSource == null)
                {
                    navigationSource = OeEdmClrHelper.GetEntitySet(_edmModel, navigationSegment.NavigationProperty);
                }

                var expandedItem = new ExpandedNavigationSelectItem(new ODataExpandPath(item.SelectedPath), navigationSource, new SelectExpandClause(null, true));
                AddOrGetNavigationItem(parentNavigationItem, expandedItem, false);
            }
            else if (item.SelectedPath.LastSegment is PropertySegment propertySegment)
            {
                parentNavigationItem.AddStructuralItem(propertySegment.Property, _notSelected);
            }
            else
            {
                throw new InvalidOperationException(item.SelectedPath.LastSegment.GetType().Name + " not supported");
            }
        }
        private static List <OeNavigationSelectItem> FlattenNavigationItems(OeNavigationSelectItem root, bool includeNextLink)
        {
            var navigationItems = new List <OeNavigationSelectItem>();
            var stack           = new Stack <ValueTuple <OeNavigationSelectItem, int> >();

            stack.Push(new ValueTuple <OeNavigationSelectItem, int>(root, 0));
            do
            {
                ValueTuple <OeNavigationSelectItem, int> stackItem = stack.Pop();
                if (stackItem.Item2 == 0 && (includeNextLink || stackItem.Item1.Kind != OeNavigationSelectItemKind.NextLink))
                {
                    navigationItems.Add(stackItem.Item1);
                }

                if (stackItem.Item2 < stackItem.Item1.NavigationItems.Count)
                {
                    stack.Push(new ValueTuple <OeNavigationSelectItem, int>(stackItem.Item1, stackItem.Item2 + 1));
                    OeNavigationSelectItem selectItem = stackItem.Item1.NavigationItems[stackItem.Item2];
                    stack.Push(new ValueTuple <OeNavigationSelectItem, int>(selectItem, 0));
                }
            }while (stack.Count > 0);
            return(navigationItems);
        }
        private OeNavigationSelectItem AddOrGetNavigationItem(OeNavigationSelectItem parentNavigationItem, ExpandedNavigationSelectItem item, bool isExpand)
        {
            IEdmEntitySetBase entitySet = OeEdmClrHelper.GetEntitySet(_edmModel, item);

            OeNavigationSelectItemKind kind;

            if (_notSelected)
            {
                kind = OeNavigationSelectItemKind.NotSelected;
            }
            else if (item.SelectAndExpand.IsNextLink())
            {
                kind = OeNavigationSelectItemKind.NextLink;
            }
            else
            {
                kind = OeNavigationSelectItemKind.Normal;
            }

            var childNavigationSelectItem = new OeNavigationSelectItem(entitySet, parentNavigationItem, item, kind);

            return(parentNavigationItem.AddOrGetNavigationItem(childNavigationSelectItem, isExpand));
        }
Example #22
0
        private Expression BuildJoin(Expression source, IList <OeNavigationSelectItem> navigationItems)
        {
            for (int i = 1; i < navigationItems.Count; i++)
            {
                OeNavigationSelectItem navigationItem = navigationItems[i];
                if (navigationItem.Parent == null)
                {
                    throw new InvalidOperationException("Parent is null must be first element in " + nameof(navigationItems));
                }

                if (!navigationItem.AlreadyUsedInBuildExpression)
                {
                    navigationItem.AlreadyUsedInBuildExpression = true;

                    ODataPathSegment       segment            = navigationItem.NavigationSelectItem.PathToNavigationProperty.LastSegment;
                    IEdmNavigationProperty navigationProperty = (((NavigationPropertySegment)segment).NavigationProperty);
                    Expression             innerSource        = GetInnerSource(navigationItem);
                    source = _joinBuilder.Build(_edmModel, source, innerSource, navigationItem.Parent.GetJoinPath(), navigationProperty);
                }
            }

            _joinBuilder.Visitor.ChangeParameterType(source);
            return(source);
        }
        internal MethodCallExpression BuildExpandCount(Expression outer, Expression inner, OeNavigationSelectItem navigationItem)
        {
            IEdmNavigationProperty navigationProperty = navigationItem.EdmProperty;

            if (navigationItem.EdmProperty.ContainsTarget)
            {
                throw new InvalidOperationException("Expand cout for many-tomany not supported");
            }

            Type outerType = OeExpressionHelper.GetCollectionItemType(outer.Type);
            Type innerType = OeExpressionHelper.GetCollectionItemType(inner.Type);

            ParameterExpression outerParameter = Expression.Parameter(outerType, outerType.Name);
            IReadOnlyList <IEdmNavigationProperty> joinPath = navigationItem.Parent == null?Array.Empty <IEdmNavigationProperty>() : navigationItem.Parent.GetJoinPath();

            Expression?joinPropertyExpression = _expressionBuilder.JoinBuilder.GetJoinPropertyExpression(outerParameter, joinPath);

            if (joinPropertyExpression == null)
            {
                throw new InvalidOperationException("Outer source not found");
            }

            MethodCallExpression subquery = CreateWhereExpression(joinPropertyExpression, inner, navigationProperty);

            MethodInfo methodInfo = OeMethodInfoHelper.GetCountMethodInfo(innerType);

            subquery = Expression.Call(methodInfo, subquery);

            List <Expression> expressions = new List <Expression>();

            if (OeExpressionHelper.IsTupleType(outerParameter.Type))
            {
                expressions.AddRange(OeExpressionHelper.GetPropertyExpressions(outerParameter));
            }
            else
            {
                expressions.Add(outerParameter);
            }
            expressions.Add(OeExpressionHelper.CreateTupleExpression(new[] { subquery }));
            NewExpression newTuple = OeExpressionHelper.CreateTupleExpression(expressions);

            methodInfo = OeMethodInfoHelper.GetSelectMethodInfo(outerType, newTuple.Type);
            return(Expression.Call(methodInfo, outer, Expression.Lambda(newTuple, outerParameter)));
        }
        private static OeEntryFactory CreateEntryFactory(OeNavigationSelectItem root, Type clrType, OePropertyAccessor[] skipTokenAccessors)
        {
            ParameterExpression parameter      = Expression.Parameter(typeof(Object));
            UnaryExpression     typedParameter = Expression.Convert(parameter, clrType);

            if (!root.HasNavigationItems())
            {
                var navigationLinks = new OeEntryFactory[root.NavigationItems.Count];
                for (int i = 0; i < root.NavigationItems.Count; i++)
                {
                    OeNavigationSelectItem navigationItem = root.NavigationItems[i];
                    var nextLinkOptions = new OeEntryFactoryOptions()
                    {
                        Accessors             = Array.Empty <OePropertyAccessor>(),
                        EdmNavigationProperty = navigationItem.EdmProperty,
                        EntitySet             = navigationItem.EntitySet,
                        NavigationSelectItem  = navigationItem.NavigationSelectItem,
                        NextLink = navigationItem.Kind == OeNavigationSelectItemKind.NextLink
                    };
                    navigationLinks[i] = new OeEntryFactory(ref nextLinkOptions);
                }

                var options = new OeEntryFactoryOptions()
                {
                    Accessors          = GetAccessors(clrType, root),
                    EntitySet          = root.EntitySet,
                    NavigationLinks    = navigationLinks,
                    SkipTokenAccessors = skipTokenAccessors
                };
                root.EntryFactory = new OeEntryFactory(ref options);
            }
            else
            {
                List <OeNavigationSelectItem>    navigationItems      = FlattenNavigationItems(root, true);
                IReadOnlyList <MemberExpression> navigationProperties = OeExpressionHelper.GetPropertyExpressions(typedParameter);
                int propertyIndex = navigationProperties.Count - 1;

                for (int i = navigationItems.Count - 1; i >= 0; i--)
                {
                    OeNavigationSelectItem navigationItem = navigationItems[i];
                    if (navigationItem.Kind == OeNavigationSelectItemKind.NotSelected)
                    {
                        propertyIndex--;
                        continue;
                    }

                    OePropertyAccessor[] accessors             = Array.Empty <OePropertyAccessor>();
                    LambdaExpression?    linkAccessor          = null;
                    OeEntryFactory[]     nestedNavigationLinks = Array.Empty <OeEntryFactory>();
                    if (navigationItem.Kind != OeNavigationSelectItemKind.NextLink)
                    {
                        accessors             = GetAccessors(navigationProperties[propertyIndex].Type, navigationItem);
                        linkAccessor          = Expression.Lambda(navigationProperties[propertyIndex], parameter);
                        nestedNavigationLinks = GetNestedNavigationLinks(navigationItem);
                        propertyIndex--;
                    }

                    var options = new OeEntryFactoryOptions()
                    {
                        Accessors             = accessors,
                        EdmNavigationProperty = navigationItem.Parent == null ? null : navigationItem.EdmProperty,
                        EntitySet             = navigationItem.EntitySet,
                        LinkAccessor          = linkAccessor,
                        NavigationLinks       = nestedNavigationLinks,
                        NavigationSelectItem  = navigationItem.Parent == null ? null : navigationItem.NavigationSelectItem,
                        NextLink           = navigationItem.Kind == OeNavigationSelectItemKind.NextLink,
                        SkipTokenAccessors = skipTokenAccessors
                    };
                    navigationItem.EntryFactory = new OeEntryFactory(ref options);
                }
            }

            return(root.EntryFactory);
        }
        private static Expression SelectStructuralProperties(Expression source, OeNavigationSelectItem root)
        {
            if (!root.HasNavigationItems())
            {
                return(source);
            }

            ParameterExpression parameter          = Expression.Parameter(OeExpressionHelper.GetCollectionItemType(source.Type));
            IReadOnlyList <MemberExpression> joins = OeExpressionHelper.GetPropertyExpressions(parameter);
            var newJoins = new Expression[joins.Count];

            List <OeNavigationSelectItem> navigationItems = FlattenNavigationItems(root, false);
            bool isNavigationNullable = false;

            for (int i = 0; i < navigationItems.Count; i++)
            {
                newJoins[i]           = joins[i];
                isNavigationNullable |= i > 0 && navigationItems[i].EdmProperty.Type.IsNullable;
                if (!navigationItems[i].AllSelected)
                {
                    IReadOnlyList <OeStructuralSelectItem> structuralItems = navigationItems[i].GetStructuralItemsWithNotSelected();
                    if (structuralItems.Count > 0)
                    {
                        var properties = new Expression[structuralItems.Count];
                        for (int j = 0; j < structuralItems.Count; j++)
                        {
                            if (structuralItems[j].EdmProperty is ComputeProperty computeProperty)
                            {
                                properties[j] = new ReplaceParameterVisitor(joins[i]).Visit(computeProperty.Expression);
                            }
                            else
                            {
                                PropertyInfo property = joins[i].Type.GetPropertyIgnoreCase(structuralItems[j].EdmProperty);
                                properties[j] = Expression.Property(joins[i], property);
                            }
                        }
                        Expression newTupleExpression = OeExpressionHelper.CreateTupleExpression(properties);

                        if (isNavigationNullable)
                        {
                            UnaryExpression nullConstant = Expression.Convert(OeConstantToVariableVisitor.NullConstantExpression, newTupleExpression.Type);
                            newTupleExpression = Expression.Condition(Expression.Equal(joins[i], OeConstantToVariableVisitor.NullConstantExpression), nullConstant, newTupleExpression);
                        }
                        newJoins[i] = newTupleExpression;
                    }
                }
            }

            NewExpression    newSelectorBody  = OeExpressionHelper.CreateTupleExpression(newJoins);
            MethodInfo       selectMethodInfo = OeMethodInfoHelper.GetSelectMethodInfo(parameter.Type, newSelectorBody.Type);
            LambdaExpression newSelector      = Expression.Lambda(newSelectorBody, parameter);

            //Quirk EF Core 2.1.1 bug Take/Skip must be last in expression tree
            var skipTakeExpressions = new List <MethodCallExpression>();

            while (source is MethodCallExpression callExpression && (callExpression.Method.Name == nameof(Enumerable.Skip) || callExpression.Method.Name == nameof(Enumerable.Take)))
            {
                skipTakeExpressions.Add(callExpression);
                source = callExpression.Arguments[0];
            }

            source = Expression.Call(selectMethodInfo, source, newSelector);

            for (int i = skipTakeExpressions.Count - 1; i >= 0; i--)
            {
                MethodInfo skipTakeMethodInfo = skipTakeExpressions[i].Method.GetGenericMethodDefinition().MakeGenericMethod(newSelector.ReturnType);
                source = Expression.Call(skipTakeMethodInfo, source, skipTakeExpressions[i].Arguments[1]);
            }

            return(source);
        }
Example #26
0
        public override OeEntryFactory CreateEntryFactory(IEdmEntitySet entitySet, Type clrType, OePropertyAccessor[]?skipTokenAccessors)
        {
            ParameterExpression parameter      = Expression.Parameter(typeof(Object));
            UnaryExpression     typedParameter = Expression.Convert(parameter, clrType);

            if (_rootNavigationItem.HasNavigationItems())
            {
                List <OeNavigationSelectItem>    navigationItems      = OeSelectTranslator.FlattenNavigationItems(_rootNavigationItem, true);
                IReadOnlyList <MemberExpression> navigationProperties = OeExpressionHelper.GetPropertyExpressions(typedParameter);
                int propertyIndex = navigationProperties.Count - 1;

                for (int i = navigationItems.Count - 1; i >= 0; i--)
                {
                    OeNavigationSelectItem navigationItem = navigationItems[i];
                    if (navigationItem.Kind == OeNavigationSelectItemKind.NotSelected)
                    {
                        propertyIndex--;
                        continue;
                    }

                    OePropertyAccessor[]       accessors             = Array.Empty <OePropertyAccessor>();
                    LambdaExpression?          linkAccessor          = null;
                    OeNavigationEntryFactory[] nestedNavigationLinks = Array.Empty <OeNavigationEntryFactory>();
                    if (navigationItem.Kind != OeNavigationSelectItemKind.NextLink)
                    {
                        accessors             = GetAccessors(navigationProperties[propertyIndex].Type, navigationItem);
                        linkAccessor          = Expression.Lambda(navigationProperties[propertyIndex], parameter);
                        nestedNavigationLinks = GetNestedNavigationLinks(navigationItem);
                        propertyIndex--;
                    }

                    if (i == 0)
                    {
                        navigationItem.EntryFactory = new OeEntryFactory(navigationItem.EntitySet, accessors, skipTokenAccessors, nestedNavigationLinks, linkAccessor);
                    }
                    else
                    {
                        navigationItem.EntryFactory = new OeNavigationEntryFactory(
                            navigationItem.EntitySet,
                            accessors,
                            skipTokenAccessors,
                            nestedNavigationLinks,
                            linkAccessor,
                            navigationItem.EdmProperty,
                            navigationItem.NavigationSelectItem,
                            navigationItem.Kind == OeNavigationSelectItemKind.NextLink);
                    }
                }
            }
            else
            {
                var navigationLinks = new OeNavigationEntryFactory[_rootNavigationItem.NavigationItems.Count];
                for (int i = 0; i < _rootNavigationItem.NavigationItems.Count; i++)
                {
                    OeNavigationSelectItem navigationItem = _rootNavigationItem.NavigationItems[i];
                    navigationLinks[i] = new OeNavigationEntryFactory(
                        navigationItem.EntitySet,
                        Array.Empty <OePropertyAccessor>(),
                        null,
                        Array.Empty <OeNavigationEntryFactory>(),
                        null,
                        navigationItem.EdmProperty,
                        navigationItem.NavigationSelectItem,
                        navigationItem.Kind == OeNavigationSelectItemKind.NextLink);
                }

                OePropertyAccessor[] accessors = GetAccessors(clrType, _rootNavigationItem);
                _rootNavigationItem.EntryFactory = new OeEntryFactory(_rootNavigationItem.EntitySet, accessors, skipTokenAccessors, navigationLinks);
            }

            return(_rootNavigationItem.EntryFactory);
        }
Example #27
0
 public OeSelectEntryFactoryFactory(OeNavigationSelectItem rootNavigationItem)
 {
     _rootNavigationItem = rootNavigationItem;
 }