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); }
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); }
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); }
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))); }
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)); }
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)); }
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); }
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); } }