Ejemplo n.º 1
0
        private Expression GetInnerSource(OeSelectItem navigationItem, ExpandedNavigationSelectItem item)
        {
            Type         clrEntityType         = _visitor.EdmModel.GetClrType(navigationItem.EdmProperty.DeclaringType);
            PropertyInfo navigationClrProperty = OeEdmClrHelper.GetPropertyIgnoreCase(clrEntityType, 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);

            Expression innerSource = Expression.Constant(null, typeof(IEnumerable <>).MakeGenericType(itemType));

            innerSource = expressionBuilder.ApplyFilter(innerSource, item.FilterOption);
            if (item.SkipOption != null || item.TopOption != null)
            {
                Expression source = Expression.Constant(null, typeof(IEnumerable <>).MakeGenericType(navigationClrProperty.DeclaringType));
                innerSource = OeCrossApplyBuilder.Build(source, innerSource, item, navigationItem.Path, expressionBuilder);
            }

            return(innerSource);
        }
Ejemplo n.º 2
0
        private MethodCallExpression CreateSelectExpression(Expression source, OeJoinBuilder joinBuilder)
        {
            if (_navigationItem.HasNavigationItems)
            {
                return((MethodCallExpression)source);
            }

            if (_navigationItem.SelectItems.Count == 0)
            {
                return((MethodCallExpression)source);
            }

            var expressions = new List <Expression>(_navigationItem.SelectItems.Count);

            for (int i = 0; i < _navigationItem.SelectItems.Count; i++)
            {
                IEdmProperty edmProperty = _navigationItem.SelectItems[i].EdmProperty;
                PropertyInfo clrProperty = OeEdmClrHelper.GetPropertyIgnoreCase(_visitor.Parameter.Type, edmProperty);
                expressions.Add(Expression.MakeMemberAccess(_visitor.Parameter, clrProperty));
            }
            NewExpression newTupleExpression = OeExpressionHelper.CreateTupleExpression(expressions);

            LambdaExpression lambda           = Expression.Lambda(newTupleExpression, _visitor.Parameter);
            MethodInfo       selectMethodInfo = OeMethodInfoHelper.GetSelectMethodInfo(_visitor.Parameter.Type, newTupleExpression.Type);

            return(Expression.Call(selectMethodInfo, source, lambda));
        }
Ejemplo n.º 3
0
        private Expression GetPropertyExpression(SingleValuePropertyAccessNode nodeIn)
        {
            Expression   e        = TranslateNode(nodeIn.Source);
            PropertyInfo property = OeEdmClrHelper.GetPropertyIgnoreCase(e.Type, nodeIn.Property);

            if (property == null)
            {
                if (!OeExpressionHelper.IsTupleType(e.Type))
                {
                    throw new InvalidOperationException("must by Tuple " + e.Type.ToString());
                }

                IEdmNavigationSource navigationSource = ((ResourceRangeVariableReferenceNode)nodeIn.Source).NavigationSource;
                property = GetTuplePropertyByEntityType(e.Type, navigationSource.EntityType());
            }
            return(Expression.Property(e, property));
        }
Ejemplo n.º 4
0
        private static Expression SelectStructuralProperties(Expression source, OeSelectItem 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 <OeSelectItem> navigationItems = FlattenNavigationItems(root, true);

            for (int i = 0; i < navigationItems.Count; i++)
            {
                newJoins[i] = joins[i];
                if (navigationItems[i].SelectItems.Count > 0)
                {
                    var properties = new Expression[navigationItems[i].SelectItems.Count];
                    for (int j = 0; j < navigationItems[i].SelectItems.Count; j++)
                    {
                        if (navigationItems[i].SelectItems[j].EdmProperty is ComputeProperty computeProperty)
                        {
                            properties[j] = new ReplaceParameterVisitor(joins[i]).Visit(computeProperty.Expression);
                        }
                        else
                        {
                            PropertyInfo property = OeEdmClrHelper.GetPropertyIgnoreCase(joins[i].Type, navigationItems[i].SelectItems[j].EdmProperty);
                            properties[j] = Expression.Property(joins[i], property);
                        }
                    }
                    Expression newTupleExpression = OeExpressionHelper.CreateTupleExpression(properties);

                    if (i > 0 && navigationItems[i].EdmProperty.Type.IsNullable)
                    {
                        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);
        }