public void TypeReferenceComesFromRangeVariable() { ResourceRangeVariable rangeVariable = new ResourceRangeVariable("dogs", HardCodedTestModel.GetDogTypeReference(), HardCodedTestModel.GetDogsSet()); ResourceRangeVariableReferenceNode referenceNode = new ResourceRangeVariableReferenceNode(rangeVariable.Name, rangeVariable); referenceNode.TypeReference.FullName().Should().Be(HardCodedTestModel.GetDogTypeReference().FullName()); }
public void EntitySetComesFromRangeVariable() { ResourceRangeVariable rangeVariable = new ResourceRangeVariable("dogs", HardCodedTestModel.GetDogTypeReference(), HardCodedTestModel.GetDogsSet()); ResourceRangeVariableReferenceNode referenceNode = new ResourceRangeVariableReferenceNode(rangeVariable.Name, rangeVariable); referenceNode.NavigationSource.Should().Be(HardCodedTestModel.GetDogsSet()); }
public void RangeVariableIsSetCorrectly() { ResourceRangeVariable rangeVariable = new ResourceRangeVariable("dogs", HardCodedTestModel.GetDogTypeReference(), HardCodedTestModel.GetDogsSet()); ResourceRangeVariableReferenceNode referenceNode = new ResourceRangeVariableReferenceNode(rangeVariable.Name, rangeVariable); referenceNode.RangeVariable.ShouldBeResourceRangeVariable(HardCodedTestModel.GetDogTypeReference()).And.NavigationSource.Should().Be(HardCodedTestModel.GetDogsSet()); }
public void CreateParentShouldProduceParentUsingParameters() { SingleValueNode parent = EndPathBinder.CreateParentFromImplicitRangeVariable(this.bindingState); ResourceRangeVariableReferenceNode entityRangeVariableReferenceNode = (ResourceRangeVariableReferenceNode)parent; entityRangeVariableReferenceNode.RangeVariable.Should().BeSameAs(this.bindingState.ImplicitRangeVariable); }
public override QueryNode Visit(ResourceRangeVariableReferenceNode nodeIn) { if (nodeIn.RangeVariable.CollectionResourceNode is CollectionNavigationNode collectionNavigationNode) { return(Visit(collectionNavigationNode)); } return(nodeIn); }
/// <summary> /// Visit an ResourceRangeVariableReferenceNode /// </summary> /// <param name="nodeIn">The node to visit</param> /// <returns>The translated expression</returns> public override Expression Visit(ResourceRangeVariableReferenceNode nodeIn) { this.CheckArgumentNull(nodeIn, "ResourceRangeVariableReferenceNode"); // when this is called for a filter like svc/Customers?$filter=PersonID eq 1, nodeIn.Name has value "$it". // when this is called by any/all option, nodeIn.Name is specified by client, it can be any value. return(this.ImplicitVariableParameterExpression); }
public override string Visit(NonResourceRangeVariableReferenceNode nodeIn) => nodeIn.Name; // return base.Visit(nodeIn); public override string Visit(ResourceRangeVariableReferenceNode nodeIn) // EntityRangeVariableReferenceNode { // assert nodeIn.Name == "$it" // var r = string.Empty; // nodeIn.Name; var r = nodeIn.RangeVariable.CollectionResourceNode == null /* nodeIn.Name == "$it" */ ? string.Empty : nodeIn.Name; return(r); // + nodeIn. // return WrapWithIdent(string.Format("EntityRangeVariableReferenceNode:[{0}<={1}]", nodeIn.TypeReference, nodeIn.Name)); }
/// <summary> /// Writes ResourceRangeVariableReferenceNode to string. /// </summary> /// <param name="node">Node to write to string</param> /// <returns>String representation of node.</returns> private static string ToString(ResourceRangeVariableReferenceNode node) { return(tabHelper.Prefix + "ResourceRangeVariableReferenceNode" + tabHelper.Indent(() => tabHelper.Prefix + "Name = " + node.Name + tabHelper.Prefix + "NavigationSource = " + node.NavigationSource.Name + tabHelper.Prefix + "TypeReference = " + node.TypeReference + tabHelper.Prefix + "Range Variable = " + node.RangeVariable )); }
/// <summary> /// Translates a <see cref="EntityRangeVariableReferenceNode"/> into a corresponding <see cref="string"/>. /// </summary> /// <param name="node">The node to translate.</param> /// <returns>The translated string.</returns> public override string Visit(ResourceRangeVariableReferenceNode node) { if (node.Name == "$it") { return(string.Empty); } else { return(node.Name); } }
/// <summary> /// Translates a <see cref="ResourceRangeVariableReferenceNode"/> into a corresponding <see cref="String"/>. /// </summary> /// <param name="node">The node to translate.</param> /// <returns>The translated String.</returns> public override String Visit(ResourceRangeVariableReferenceNode node) { ExceptionUtils.CheckArgumentNotNull(node, "node"); if (node.Name == "$it") { return(String.Empty); } else { return(node.Name); } }
/// <summary> /// Bind $it to the <see cref="SingleValueOpenPropertyAccessNode"/> translated string. /// </summary> /// <param name="node">node to bind.</param> /// <param name="filterClauseRangeVariable">The <see cref="FilterClause"/> range variable.</param> /// <returns>The translated string with $it binding.</returns> private string BindSingleValueOpenPropertyAccess(SingleValueOpenPropertyAccessNode node, ResourceRangeVariable filterClauseRangeVariable) { string translatedNode = this.TranslateNode(node); ResourceRangeVariableReferenceNode rangeVariableNode = GetResourceRangeVariableReferenceNode(node); if (rangeVariableNode != null && IsDifferentSource(filterClauseRangeVariable, rangeVariableNode)) { translatedNode = ExpressionConstants.It + ExpressionConstants.SymbolForwardSlash + translatedNode; } return(translatedNode); }
private FilterClause BuildFilterClause(IEdmEntitySet entitySet, GraphQLFieldSelection selection) { ResourceRangeVariable resourceVariable = GetResorceVariable(entitySet); var resourceNode = new ResourceRangeVariableReferenceNode("", resourceVariable); BinaryOperatorNode filterExpression = BuildFilterExpression(resourceNode, selection); if (filterExpression == null) { return(null); } return(new FilterClause(filterExpression, resourceVariable)); }
internal static OrderByClause GetUniqueOrderBy(IEdmModel edmModel, IEdmEntityType edmType, OrderByClause orderByClause) { if (orderByClause != null && GetIsKey(edmType, GetEdmProperies(orderByClause))) { return(orderByClause); } IEdmEntitySet entitySet = null; foreach (IEdmEntitySet element in edmModel.EntityContainer.EntitySets()) { if (element.EntityType() == edmType) { entitySet = element; break; } } OrderByClause uniqueOrderByClause = null; foreach (IEdmStructuralProperty keyProperty in edmType.Key().Reverse()) { var entityTypeRef = (IEdmEntityTypeReference)((IEdmCollectionType)entitySet.Type).ElementType; var range = new ResourceRangeVariable("", entityTypeRef, entitySet); var source = new ResourceRangeVariableReferenceNode("$it", range); var node = new SingleValuePropertyAccessNode(source, keyProperty); uniqueOrderByClause = new OrderByClause(uniqueOrderByClause, node, OrderByDirection.Ascending, source.RangeVariable); } if (orderByClause == null) { return(uniqueOrderByClause); } var orderByClauses = new Stack <OrderByClause>(); do { orderByClauses.Push(orderByClause); orderByClause = orderByClause.ThenBy; }while (orderByClause != null); while (orderByClauses.Count > 0) { orderByClause = orderByClauses.Pop(); uniqueOrderByClause = new OrderByClause(uniqueOrderByClause, orderByClause.Expression, orderByClause.Direction, orderByClause.RangeVariable); } return(uniqueOrderByClause); }
private static FilterClause MergeFilterClause(IEdmEntitySet entitySet, IEdmNavigationProperty navigationProperty, FilterClause source, FilterClause target) { ResourceRangeVariable resourceVariable = GetResorceVariable(entitySet); ResourceRangeVariableReferenceNode resourceNode = new ResourceRangeVariableReferenceNode("", resourceVariable); ChangeNavigationPathVisitor visitor = new ChangeNavigationPathVisitor(resourceNode, navigationProperty); SingleValueNode expression = visitor.Visit((BinaryOperatorNode)source.Expression); if (target != null) { expression = new BinaryOperatorNode(BinaryOperatorKind.And, target.Expression, expression); } return(new FilterClause(expression, resourceVariable)); }
public void ShouldThrowNotImplementedIfTypeIsOpen() { const string OpenPropertyName = "Style"; var token = new EndPathToken(OpenPropertyName, new RangeVariableToken("a")); CollectionResourceNode entityCollectionNode = new EntitySetNode(HardCodedTestModel.GetPaintingsSet()); SingleValueNode parentNode = new ResourceRangeVariableReferenceNode("a", new ResourceRangeVariable("a", HardCodedTestModel.GetPaintingTypeReference(), entityCollectionNode)); var state = new BindingState(this.configuration); var metadataBinder = new MetadataBinder(state); var endPathBinder = new EndPathBinder(metadataBinder.Bind, state); var propertyNode = endPathBinder.GeneratePropertyAccessQueryForOpenType( token, parentNode); propertyNode.ShouldBeSingleValueOpenPropertyAccessQueryNode(OpenPropertyName); }
private static FilterClause CreateFilterClause(IEdmEntitySet entitySet, IEnumerable <KeyValuePair <String, Object> > keys) { ResourceRangeVariableReferenceNode refNode = OeEdmClrHelper.CreateRangeVariableReferenceNode(entitySet); var entityType = (IEdmEntityType)refNode.RangeVariable.TypeReference.Definition; var propertyValues = new List <KeyValuePair <IEdmStructuralProperty, Object> >(); foreach (KeyValuePair <String, Object> keyValue in keys) { var property = (IEdmStructuralProperty)entityType.FindProperty(keyValue.Key); propertyValues.Add(new KeyValuePair <IEdmStructuralProperty, Object>(property, keyValue.Value)); } return(new FilterClause(CreateFilterExpression(refNode, propertyValues), refNode.RangeVariable)); }
private static FilterClause CreateFilterClause(IEdmEntitySet entitySet, IEdmEntityTypeReference entityTypeRef, KeySegment keySegment) { var range = new ResourceRangeVariable("", entityTypeRef, entitySet); var refNode = new ResourceRangeVariableReferenceNode("$it", range); var pair = keySegment.Keys.Single(); var entityType = (IEdmEntityType)keySegment.EdmType; IEdmProperty property = entityType.FindProperty(pair.Key); var left = new SingleValuePropertyAccessNode(refNode, property); var right = new ConstantNode(pair.Value, ODataUriUtils.ConvertToUriLiteral(pair.Value, ODataVersion.V4)); var node = new BinaryOperatorNode(BinaryOperatorKind.Equal, left, right); return(new FilterClause(node, range)); }
public void ShouldThrowIfTypeNotOpen() { var token = new EndPathToken("Color", new RangeVariableToken("a")); CollectionResourceNode entityCollectionNode = new EntitySetNode(HardCodedTestModel.GetDogsSet()); SingleValueNode parentNode = new ResourceRangeVariableReferenceNode("a", new ResourceRangeVariable("a", HardCodedTestModel.GetPersonTypeReference(), entityCollectionNode)); var state = new BindingState(this.configuration); var metadataBinder = new MetadataBinder(state); var endPathBinder = new EndPathBinder(metadataBinder.Bind, state); Action getQueryNode = () => endPathBinder.GeneratePropertyAccessQueryForOpenType( token, parentNode); getQueryNode.Throws <ODataException>( Strings.MetadataBinder_PropertyNotDeclared(parentNode.GetEdmTypeReference().FullName(), token.Identifier)); }
private static List <SingleValuePropertyAccessNode> GetOrderByProperties(IEdmEntitySetBase entitySet, OrderByClause?orderByClause, ApplyClause?applyClause) { var keys = new List <SingleValuePropertyAccessNode>(); GroupByTransformationNode groupByNode; if (applyClause != null && (groupByNode = applyClause.Transformations.OfType <GroupByTransformationNode>().SingleOrDefault()) != null) { foreach (GroupByPropertyNode node in groupByNode.GroupingProperties) { if (node.Expression == null) { keys.AddRange(node.ChildTransformations.Select(n => (SingleValuePropertyAccessNode)n.Expression)); } else { keys.Add((SingleValuePropertyAccessNode)node.Expression); } } } else { ResourceRangeVariableReferenceNode source = OeEdmClrHelper.CreateRangeVariableReferenceNode(entitySet); foreach (IEdmStructuralProperty key in entitySet.EntityType().Key()) { keys.Add(new SingleValuePropertyAccessNode(source, key)); } } if (orderByClause == null) { return(keys); } for (; orderByClause != null; orderByClause = orderByClause.ThenBy) { if (orderByClause.Expression is SingleValuePropertyAccessNode propertyNode) { int i = keys.FindIndex(p => p.Property == propertyNode.Property); if (i >= 0) { keys.RemoveAt(i); } } } return(keys); }
public void ShouldNotThrowIfTypeNotOpenButAggregateApplied() { var token = new EndPathToken("Color", new RangeVariableToken("a")); CollectionResourceNode entityCollectionNode = new EntitySetNode(HardCodedTestModel.GetDogsSet()); SingleValueNode parentNode = new ResourceRangeVariableReferenceNode("a", new ResourceRangeVariable("a", HardCodedTestModel.GetPersonTypeReference(), entityCollectionNode)); var state = new BindingState(this.configuration); state.AggregatedPropertyNames = new HashSet <EndPathToken> { new EndPathToken("Color", new RangeVariableToken("a")) }; var metadataBinder = new MetadataBinder(state); var endPathBinder = new EndPathBinder(metadataBinder.Bind, state); var propertyNode = endPathBinder.GeneratePropertyAccessQueryForOpenType( token, parentNode); propertyNode.ShouldBeSingleValueOpenPropertyAccessQueryNode("Color"); }
private static Uri BuildNavigationNextPageLink(OeEntryFactory entryFactory, ExpandedNavigationSelectItem expandedNavigationSelectItem, Object value) { var segment = (NavigationPropertySegment)expandedNavigationSelectItem.PathToNavigationProperty.LastSegment; IEdmNavigationProperty navigationProperty = segment.NavigationProperty; if (navigationProperty.IsPrincipal()) { navigationProperty = navigationProperty.Partner; } var keys = new List <KeyValuePair <IEdmStructuralProperty, Object> >(); IEnumerator <IEdmStructuralProperty> dependentProperties = navigationProperty.DependentProperties().GetEnumerator(); foreach (IEdmStructuralProperty key in navigationProperty.PrincipalProperties()) { dependentProperties.MoveNext(); Object keyValue = entryFactory.GetAccessorByName(key.Name).GetValue(value); keys.Add(new KeyValuePair <IEdmStructuralProperty, Object>(dependentProperties.Current, keyValue)); } ResourceRangeVariableReferenceNode refNode = OeEdmClrHelper.CreateRangeVariableReferenceNode((IEdmEntitySet)segment.NavigationSource); BinaryOperatorNode filterExpression = OeGetParser.CreateFilterExpression(refNode, keys); if (expandedNavigationSelectItem.FilterOption != null) { filterExpression = new BinaryOperatorNode(BinaryOperatorKind.And, filterExpression, expandedNavigationSelectItem.FilterOption.Expression); } var segments = new ODataPathSegment[] { new EntitySetSegment((IEdmEntitySet)refNode.NavigationSource) }; var odataUri = new ODataUri() { Path = new ODataPath(segments), 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)); }
public override QueryNode Visit(ResourceRangeVariableReferenceNode node) { if (_rangeVariable.NavigationSource != node.RangeVariable.NavigationSource) { foreach (IEdmNavigationPropertyBinding propertyBinding in _rangeVariable.NavigationSource.NavigationPropertyBindings) { if (propertyBinding.Target == node.RangeVariable.NavigationSource) { EdmMultiplicity multiplicity = propertyBinding.NavigationProperty.TargetMultiplicity(); if (multiplicity == EdmMultiplicity.One || multiplicity == EdmMultiplicity.ZeroOrOne) { var rangeVariableNode = new ResourceRangeVariableReferenceNode("", _rangeVariable); return(new SingleNavigationNode(rangeVariableNode, propertyBinding.NavigationProperty, propertyBinding.Path)); } } } } return(node); }
/// <summary> /// Bind $it to the <see cref="AnyNode"/> translated string. /// </summary> /// <param name="node">node to bind.</param> /// <param name="filterClauseRangeVariable">The <see cref="FilterClause"/> range variable.</param> /// <returns>The translated string with $it binding.</returns> private string BindAnyNode(AnyNode node, ResourceRangeVariable filterClauseRangeVariable) { string translatedNode = this.TranslateNode(node); ResourceRangeVariableReferenceNode leftRangeVariableNode = GetResourceRangeVariableReferenceNode(node); const string slashAny = "/any"; string[] anySeparator = { slashAny }; string[] substrings = translatedNode.Trim().Split(anySeparator, StringSplitOptions.RemoveEmptyEntries); string leftAnyNodeSubstring = substrings[0]; string rightAnyNodeSubstring = substrings[1]; if (leftRangeVariableNode != null && IsDifferentSource(filterClauseRangeVariable, leftRangeVariableNode)) { leftAnyNodeSubstring = ExpressionConstants.It + ExpressionConstants.SymbolForwardSlash + leftAnyNodeSubstring; translatedNode = leftAnyNodeSubstring + slashAny + rightAnyNodeSubstring; } return(translatedNode); }
/// <summary> /// Bind $it to the <see cref="InNode"/> translated string. /// </summary> /// <param name="node">node to bind.</param> /// <param name="filterClauseRangeVariable">The <see cref="FilterClause"/> range variable.</param> /// <returns>The translated string with $it binding.</returns> private string BindInNode(InNode node, ResourceRangeVariable filterClauseRangeVariable) { string translatedNode = this.TranslateNode(node); ResourceRangeVariableReferenceNode leftRangeVariableNode = GetResourceRangeVariableReferenceNode(node.Left); string inOperator = ExpressionConstants.KeywordIn; string[] inSeparator = { inOperator }; string[] substrings = translatedNode.Trim().Split(inSeparator, StringSplitOptions.RemoveEmptyEntries); string leftIn = substrings[0]; string rightIn = substrings[1]; if (leftRangeVariableNode != null && IsDifferentSource(filterClauseRangeVariable, leftRangeVariableNode)) { leftIn = ExpressionConstants.It + ExpressionConstants.SymbolForwardSlash + leftIn; translatedNode = leftIn + inOperator + rightIn; } return(translatedNode); }
/// <summary> /// Compares entity parameter query nodes query nodes. /// </summary> /// <param name="left">Left side of comparison</param> /// <param name="right">Right side of comparison</param> /// <returns>True if equal, otherwise false</returns> private bool Compare(ResourceRangeVariableReferenceNode left, ResourceRangeVariableReferenceNode right) { if (left.Name != right.Name) { return(false); } if (left.TypeReference != right.TypeReference) { return(false); } if (left.NavigationSource != right.NavigationSource) { return(false); } if (left.StructuredTypeReference != right.StructuredTypeReference) { return(false); } return(true); }
private bool Visit(ResourceRangeVariableReferenceNode node1, ResourceRangeVariableReferenceNode node2) { if (node1.Name != node2.Name) { return(false); } if (node1.NavigationSource != node2.NavigationSource) { return(false); } if (!Compare(node1.RangeVariable, node2.RangeVariable)) { return(false); } if (!node1.StructuredTypeReference.IsEqual(node2.StructuredTypeReference)) { return(false); } return(node1.TypeReference.IsEqual(node2.TypeReference)); }
internal static BinaryOperatorNode CreateFilterExpression(ResourceRangeVariableReferenceNode referenceNode, IEnumerable <KeyValuePair <IEdmStructuralProperty, Object> > keys) { BinaryOperatorNode compositeNode = null; foreach (KeyValuePair <IEdmStructuralProperty, Object> keyValue in keys) { var left = new SingleValuePropertyAccessNode(referenceNode, keyValue.Key); var right = new ConstantNode(keyValue.Value, ODataUriUtils.ConvertToUriLiteral(keyValue.Value, ODataVersion.V4)); var node = new BinaryOperatorNode(BinaryOperatorKind.Equal, left, right); if (compositeNode == null) { compositeNode = node; } else { compositeNode = new BinaryOperatorNode(BinaryOperatorKind.And, compositeNode, node); } } return(compositeNode); }
/// <summary> /// Bind $it to the <see cref="SingleValueFunctionCallNode"/> translated string. /// </summary> /// <param name="node">node to bind.</param> /// <param name="filterClauseRangeVariable">The <see cref="FilterClause"/> range variable.</param> /// <returns>The translated string with $it binding.</returns> private string BindSingleValueFunctionCallNode(SingleValueFunctionCallNode node, ResourceRangeVariable filterClauseRangeVariable) { string translatedNode = this.TranslateNode(node); ResourceRangeVariableReferenceNode firstParameterRangeVariableNode = GetResourceRangeVariableReferenceNode(node); char[] separators = { '(', ')' }; string[] subtrings = translatedNode.Trim().Split(separators, StringSplitOptions.RemoveEmptyEntries); string withinBrackets = subtrings[1]; char[] parameterSeparators = { ',' }; string[] parameters = withinBrackets.Trim().Split(parameterSeparators, StringSplitOptions.RemoveEmptyEntries); string leftParameter = parameters[0]; string rightParameter = parameters.Length == 2 ? parameters[1] : String.Empty; if (firstParameterRangeVariableNode != null && IsDifferentSource(filterClauseRangeVariable, firstParameterRangeVariableNode)) { leftParameter = ExpressionConstants.It + ExpressionConstants.SymbolForwardSlash + leftParameter; translatedNode = parameters.Length == 1 ? subtrings[0] + '(' + leftParameter + ')' : subtrings[0] + '(' + leftParameter + ',' + rightParameter + ')'; } return(translatedNode); }
/// <summary> /// Check whether Navigation source of the FilterClause rangeVariable is different from the Expression rangeVariable. /// </summary> /// <param name="node">Expression node.</param> /// <returns>If Navigation Source are different, returns true. Otherwise false.</returns> private bool IsDifferentSource(QueryNode node) { ResourceRangeVariableReferenceNode rangeVariableReferenceNode = GetResourceRangeVariableReferenceNode(node); if (rangeVariableReferenceNode == null) { return(false); } if (rangeVariables.Count == 0) { return(false); } RangeVariable rangeVariable = rangeVariables.Peek(); if (rangeVariable == null) { return(false); } return(rangeVariable is ResourceRangeVariable resourceRangeVariable ? resourceRangeVariable.NavigationSource != rangeVariableReferenceNode.NavigationSource && rangeVariableReferenceNode.Name == ExpressionConstants.It : 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); }