public void ItemTypeShouldBeExactlyFromPropertyType() { var source = FakeSingleEntityNode.CreateFakeSingleEntityNodeForDog(); var node = new CollectionNavigationNode(source, HardCodedTestModel.GetDogMyPeopleNavProp(), new EdmPathExpression("MyPeople")); node.ItemType.Should().BeSameAs(HardCodedTestModel.GetDogMyPeopleNavProp().Type.AsCollection().CollectionDefinition().ElementType); }
public void SourceShouldBeSet() { var source = FakeSingleEntityNode.CreateFakeSingleEntityNodeForDog(); var node = new CollectionNavigationNode(source, HardCodedTestModel.GetDogMyPeopleNavProp(), new EdmPathExpression("MyPeople")); node.Source.Should().BeSameAs(source); }
public void CollectionTypeShouldBeExactlyFromPropertyType() { var source = FakeSingleEntityNode.CreateFakeSingleEntityNodeForDog(); var node = new CollectionNavigationNode(HardCodedTestModel.GetDogMyPeopleNavProp(), source); node.CollectionType.Should().BeSameAs(HardCodedTestModel.GetDogMyPeopleNavProp().Type.AsCollection()); }
/// <summary> /// Builds an appropriate navigation query node (collection or single) for the given property and parent node. /// </summary> /// <param name="property">Navigation property.</param> /// <param name="parent">Parent Node.</param> /// <param name="namedValues">Named values (key values) that were included in the node we are binding, if any.</param> /// <param name="state">State of binding.</param> /// <param name="keyBinder">Object to perform binding on any key values that are present.</param> /// <returns>A new CollectionNavigationNode or SingleNavigationNode to capture the navigation propety access.</returns> internal static QueryNode GetNavigationNode(IEdmNavigationProperty property, SingleEntityNode parent, IEnumerable <NamedValue> namedValues, BindingState state, KeyBinder keyBinder) { ExceptionUtils.CheckArgumentNotNull(property, "property"); ExceptionUtils.CheckArgumentNotNull(parent, "parent"); ExceptionUtils.CheckArgumentNotNull(state, "state"); ExceptionUtils.CheckArgumentNotNull(keyBinder, "keyBinder"); // Handle collection navigation property if (property.TargetMultiplicity() == EdmMultiplicity.Many) { CollectionNavigationNode collectionNavigationNode = new CollectionNavigationNode(property, parent); // Doing key lookup on the collection navigation property if (namedValues != null) { return(keyBinder.BindKeyValues(collectionNavigationNode, namedValues, state.Model)); } // Otherwise it's just a normal collection of entities return(collectionNavigationNode); } Debug.Assert(namedValues == null || !namedValues.Any(), "namedValues should not exist if it isn't a colleciton"); // Otherwise it's a single navigation property return(new SingleNavigationNode(property, parent)); }
public void CollectionNavigationNodeHandlesNullEntitySetOnParentNode() { var source = new FakeSingleEntityNode(HardCodedTestModel.GetDogTypeReference(), null); var collectionCastNode = new CollectionNavigationNode(HardCodedTestModel.GetDogMyPeopleNavProp(), source); collectionCastNode.NavigationSource.Should().BeNull(); }
public void CollectionNavigationNodeHandlesNullEntitySetOnParentNode() { var source = new FakeSingleEntityNode(HardCodedTestModel.GetDogTypeReference(), null); var collectionCastNode = new CollectionNavigationNode(source, HardCodedTestModel.GetDogMyPeopleNavProp(), new EdmPathExpression("MyPeople")); Assert.Null(collectionCastNode.NavigationSource); }
/// <summary> /// Binds a <see cref="CollectionNode"/> to create a LINQ <see cref="Expression"/> that represents the semantics /// of the <see cref="CollectionNode"/>. /// </summary> /// <param name="node">The node to bind.</param> /// <returns>The LINQ <see cref="Expression"/> created.</returns> private Expression BindCollectionNode(CollectionNode node) { switch (node.Kind) { case QueryNodeKind.CollectionNavigationNode: CollectionNavigationNode navigationNode = node as CollectionNavigationNode; return(BindNavigationPropertyNode(navigationNode.Source, navigationNode.NavigationProperty)); case QueryNodeKind.CollectionPropertyAccess: return(BindCollectionPropertyAccessNode(node as CollectionPropertyAccessNode)); case QueryNodeKind.CollectionComplexNode: return(BindCollectionComplexNode(node as CollectionComplexNode)); case QueryNodeKind.CollectionResourceCast: return(BindCollectionResourceCastNode(node as CollectionResourceCastNode)); case QueryNodeKind.CollectionConstant: return(BindCollectionConstantNode(node as CollectionConstantNode)); case QueryNodeKind.CollectionFunctionCall: case QueryNodeKind.CollectionResourceFunctionCall: case QueryNodeKind.CollectionOpenPropertyAccess: default: throw Error.NotSupported(SRResources.QueryNodeBindingNotSupported, node.Kind, typeof(FilterBinder).Name); } }
public override Expression Visit(CollectionNavigationNode nodeIn) { Expression source = TranslateNode(nodeIn.Source); PropertyInfo propertyInfo = source.Type.GetPropertyIgnoreCase(nodeIn.NavigationProperty); return(Expression.Property(source, propertyInfo)); }
public void EntitySetShouldBeSet() { var source = FakeSingleEntityNode.CreateFakeSingleEntityNodeForDog(); var node = new CollectionNavigationNode(HardCodedTestModel.GetDogMyPeopleNavProp(), source); node.NavigationSource.Should().BeSameAs(HardCodedTestModel.GetPeopleSet()); }
private void ValidateCollectionNode(CollectionNode node, ODataValidationSettings settings) { switch (node.Kind) { case QueryNodeKind.CollectionPropertyAccess: CollectionPropertyAccessNode propertyAccessNode = node as CollectionPropertyAccessNode; ValidateCollectionPropertyAccessNode(propertyAccessNode, settings); break; case QueryNodeKind.CollectionComplexNode: CollectionComplexNode collectionComplexNode = node as CollectionComplexNode; ValidateCollectionComplexNode(collectionComplexNode, settings); break; case QueryNodeKind.CollectionNavigationNode: CollectionNavigationNode navigationNode = node as CollectionNavigationNode; ValidateNavigationPropertyNode(navigationNode.Source, navigationNode.NavigationProperty, settings); break; case QueryNodeKind.CollectionResourceCast: ValidateCollectionResourceCastNode(node as CollectionResourceCastNode, settings); break; case QueryNodeKind.CollectionFunctionCall: case QueryNodeKind.CollectionResourceFunctionCall: case QueryNodeKind.CollectionOpenPropertyAccess: // Unused or have unknown uses. default: throw Error.NotSupported(SRResources.QueryNodeValidationNotSupported, node.Kind, typeof(FilterQueryValidator).Name); } }
public void EntityItemTypeShouldBeSameAsItemType() { var source = FakeSingleEntityNode.CreateFakeSingleEntityNodeForDog(); var node = new CollectionNavigationNode(HardCodedTestModel.GetDogMyPeopleNavProp(), source); node.EntityItemType.Should().BeSameAs(node.ItemType); }
private AggregateExpressionBase BindAggregateExpressionToken(AggregateTokenBase aggregateToken) { switch (aggregateToken.Kind) { case QueryTokenKind.AggregateExpression: { AggregateExpressionToken token = aggregateToken as AggregateExpressionToken; SingleValueNode expression = this.bindMethod(token.Expression) as SingleValueNode; IEdmTypeReference typeReference = CreateAggregateExpressionTypeReference(expression, token.MethodDefinition); // TODO: Determine source return(new AggregateExpression(expression, token.MethodDefinition, token.Alias, typeReference)); } case QueryTokenKind.EntitySetAggregateExpression: { EntitySetAggregateToken token = aggregateToken as EntitySetAggregateToken; CollectionNavigationNode expression = this.bindMethod(token.EntitySet) as CollectionNavigationNode; IEnumerable <AggregateExpressionBase> children = token.Expressions.Select(x => BindAggregateExpressionToken(x)); return(new EntitySetAggregateExpression(expression, children)); } default: throw new ODataException(ODataErrorStrings.ApplyBinder_UnsupportedAggregateKind(aggregateToken.Kind)); } }
public void CollectionTypeShouldBeExactlyFromPropertyType() { var source = FakeSingleEntityNode.CreateFakeSingleEntityNodeForDog(); var node = new CollectionNavigationNode(source, HardCodedTestModel.GetDogMyPeopleNavProp(), new EdmPathExpression("MyPeople")); Assert.Same(node.CollectionType, HardCodedTestModel.GetDogMyPeopleNavProp().Type.AsCollection()); }
public void EntitySetShouldBeSet() { var source = FakeSingleEntityNode.CreateFakeSingleEntityNodeForDog(); var node = new CollectionNavigationNode(source, HardCodedTestModel.GetDogMyPeopleNavProp(), new EdmPathExpression("MyPeople")); Assert.Same(node.NavigationSource, HardCodedTestModel.GetPeopleSet()); }
/// <summary> /// We return the <see cref="ResourceRangeVariableReferenceNode"/> within a <see cref="QueryNode"/> /// </summary> /// <param name="node">The node to extract the ResourceRangeVariableReferenceNode.</param> /// <returns>The extracted ResourceRangeVariableReferenceNode.</returns> private ResourceRangeVariableReferenceNode GetResourceRangeVariableReferenceNode(QueryNode node) { if (node == null) { return(null); } switch (node.Kind) { case QueryNodeKind.SingleValuePropertyAccess: SingleValuePropertyAccessNode singleValuePropertyAccessNode = node as SingleValuePropertyAccessNode; return(GetResourceRangeVariableReferenceNode(singleValuePropertyAccessNode.Source)); case QueryNodeKind.Convert: ConvertNode convertNode = node as ConvertNode; return(GetResourceRangeVariableReferenceNode(convertNode.Source)); case QueryNodeKind.Any: AnyNode anyNode = node as AnyNode; return(GetResourceRangeVariableReferenceNode(anyNode.Source)); case QueryNodeKind.SingleValueFunctionCall: SingleValueFunctionCallNode singleValueFunctionCallNode = node as SingleValueFunctionCallNode; return(GetResourceRangeVariableReferenceNode(singleValueFunctionCallNode.Parameters.First())); case QueryNodeKind.ResourceRangeVariableReference: return(node as ResourceRangeVariableReferenceNode); case QueryNodeKind.SingleValueOpenPropertyAccess: SingleValueOpenPropertyAccessNode singleValueOpenPropertyAccessNode = node as SingleValueOpenPropertyAccessNode; return(GetResourceRangeVariableReferenceNode(singleValueOpenPropertyAccessNode.Source)); case QueryNodeKind.SingleComplexNode: SingleComplexNode singleComplexNode = node as SingleComplexNode; return(GetResourceRangeVariableReferenceNode(singleComplexNode.Source)); case QueryNodeKind.CollectionComplexNode: CollectionComplexNode collectionComplexNode = node as CollectionComplexNode; return(GetResourceRangeVariableReferenceNode(collectionComplexNode.Source)); case QueryNodeKind.CollectionNavigationNode: CollectionNavigationNode collectionNavigationNode = node as CollectionNavigationNode; return(GetResourceRangeVariableReferenceNode(collectionNavigationNode.Source)); case QueryNodeKind.SingleNavigationNode: SingleNavigationNode singleNavigationNode = node as SingleNavigationNode; return(GetResourceRangeVariableReferenceNode(singleNavigationNode.Source)); case QueryNodeKind.CollectionResourceFunctionCall: CollectionResourceFunctionCallNode collectionResourceFunctionCallNode = node as CollectionResourceFunctionCallNode; return(GetResourceRangeVariableReferenceNode(collectionResourceFunctionCallNode.Source)); case QueryNodeKind.SingleResourceFunctionCall: SingleResourceFunctionCallNode singleResourceFunctionCallNode = node as SingleResourceFunctionCallNode; return(GetResourceRangeVariableReferenceNode(singleResourceFunctionCallNode.Source)); } return(null); }
protected string Bind(QueryNode node) { CollectionNode collectionNode = node as CollectionNode; SingleValueNode singleValueNode = node as SingleValueNode; if (collectionNode != null) { switch (node.Kind) { case QueryNodeKind.CollectionNavigationNode: CollectionNavigationNode navigationNode = node as CollectionNavigationNode; return(BindNavigationPropertyNode(navigationNode.Source, navigationNode.NavigationProperty)); case QueryNodeKind.CollectionPropertyAccess: return(BindCollectionPropertyAccessNode(node as CollectionPropertyAccessNode)); } } else if (singleValueNode != null) { switch (node.Kind) { case QueryNodeKind.BinaryOperator: return(BindBinaryOperatorNode(node as BinaryOperatorNode)); case QueryNodeKind.Constant: return(BindConstantNode(node as ConstantNode)); case QueryNodeKind.Convert: return(BindConvertNode(node as ConvertNode)); case QueryNodeKind.EntityRangeVariableReference: return(BindRangeVariable((node as EntityRangeVariableReferenceNode).RangeVariable)); case QueryNodeKind.NonentityRangeVariableReference: return(BindRangeVariable((node as NonentityRangeVariableReferenceNode).RangeVariable)); case QueryNodeKind.SingleValuePropertyAccess: return(BindPropertyAccessQueryNode(node as SingleValuePropertyAccessNode)); case QueryNodeKind.UnaryOperator: return(BindUnaryOperatorNode(node as UnaryOperatorNode)); case QueryNodeKind.SingleValueFunctionCall: return(BindSingleValueFunctionCallNode(node as SingleValueFunctionCallNode)); case QueryNodeKind.SingleNavigationNode: SingleNavigationNode navigationNode = node as SingleNavigationNode; return(BindNavigationPropertyNode(navigationNode.Source, navigationNode.NavigationProperty)); case QueryNodeKind.Any: return(BindAnyNode(node as AnyNode)); case QueryNodeKind.All: return(BindAllNode(node as AllNode)); } } throw new NotSupportedException(String.Format("Nodes of type {0} are not supported", node.Kind)); }
public override IEnumerable <string> Visit(CollectionNavigationNode nodeIn) { Console.WriteLine("CNN"); return(new[] { Combine(nodeIn.Source, nodeIn.NavigationProperty.Name) }); }
/// <summary> /// Translate a CollectionNavigationNode. /// </summary> /// <param name="nodeIn">The node to be translated.</param> /// <returns>The translated node.</returns> public override QueryNode Visit(CollectionNavigationNode nodeIn) { return(nodeIn.Source == null ? nodeIn : new CollectionNavigationNode( nodeIn.NavigationProperty, (SingleEntityNode)nodeIn.Source.Accept(this))); }
private static void BuildFilterWithBinaryOperator() { var personTypeRef = new EdmEntityTypeReference(TripPinModel.Person, false); var friendsProp = (IEdmNavigationProperty)TripPinModel.Person.FindProperty("Friends"); var firstNameProp = TripPinModel.Person.FindProperty("FirstName"); var lastNameProp = TripPinModel.Person.FindProperty("LastName"); var topIt = new EntityRangeVariable("$it", personTypeRef, TripPinModel.PeopleSet); var topItRef = new EntityRangeVariableReferenceNode("$it", topIt); var friendsNavNode = new CollectionNavigationNode(friendsProp, topItRef); var e0 = new EntityRangeVariable("e0", personTypeRef, friendsNavNode); var e0Ref = new EntityRangeVariableReferenceNode("e0", e0); var fun1 = new SingleValueFunctionCallNode( "startswith", new QueryNode[] { new SingleValuePropertyAccessNode(e0Ref, firstNameProp), new ConstantNode("var1", "'var1'") }, EdmCoreModel.Instance.GetBoolean(false)); var friendsNavNode2 = new CollectionNavigationNode(friendsProp, e0Ref); var e1 = new EntityRangeVariable("e1", personTypeRef, friendsNavNode2); var e1Ref = new EntityRangeVariableReferenceNode("e1", e1); var fun2 = new SingleValueFunctionCallNode( "contains", new QueryNode[] { new SingleValuePropertyAccessNode(e1Ref, lastNameProp), new ConstantNode("var2", "'var2'") }, EdmCoreModel.Instance.GetBoolean(false)); // Actually $it also needed, but would not be used in UriBuilder, so omit it here. var any2 = new AnyNode(new Collection<RangeVariable> { e1 }, e1) { Body = fun2, Source = friendsNavNode2 }; var any1 = new AnyNode(new Collection<RangeVariable> { e0 }, e0) { Body = new BinaryOperatorNode(BinaryOperatorKind.And, fun1, any2), Source = friendsNavNode }; var odataUri = new ODataUri { Path = new ODataPath(new EntitySetSegment(TripPinModel.PeopleSet)), ServiceRoot = TripPinRoot, Filter = new FilterClause(any1, topIt) }; var builder = new ODataUriBuilder(ODataUrlConventions.Default, odataUri); Console.WriteLine(builder.BuildUri()); // http://services.odata.org/V4/TripPinService/People?$filter=Friends%2Fany( // e0:startswith(e0%2FFirstName%2C'var1') and e0%2FFriends%2Fany(e1:contains(e1%2FLastName%2C'var2'))) }
/// <summary> /// Visit a CollectionNavigationNode /// </summary> /// <param name="nodeIn">the node to visit</param> /// <returns>true, indicating that the node has been visited.</returns> public override bool Visit(CollectionNavigationNode nodeIn) { validate(nodeIn); validate(nodeIn.NavigationProperty); // don't validate TypeReferences, only types, as nullability is only meaningful in context of model element validate(nodeIn.CollectionType.CollectionDefinition()); validate(nodeIn.ItemType.Definition); return(true); }
/// <summary> /// Translate a CollectionNavigationNode. /// </summary> /// <param name="nodeIn">The node to be translated.</param> /// <returns>The translated node.</returns> public override QueryNode Visit(CollectionNavigationNode nodeIn) { return(nodeIn.Source == null ? nodeIn : new CollectionNavigationNode( (SingleResourceNode)nodeIn.Source.Accept(this), nodeIn.NavigationProperty, nodeIn.BindingPath ?? new EdmPathExpression(nodeIn.NavigationProperty.Name))); }
public override QueryNode Visit(CollectionNavigationNode nodeIn) { SingleResourceNode?source = nodeIn.Source == null ? null : (SingleResourceNode)Visit(nodeIn.Source); if (nodeIn.Source != source) { nodeIn = new CollectionNavigationNode(source, nodeIn.NavigationProperty, nodeIn.BindingPath); } return(nodeIn); }
/// <inheritdoc /> public override string Visit(CollectionNavigationNode node) { var navigationPath = GetNavigationPath(node); if (navigationPath.StartsWith($"{Constants.SQLFieldNameSymbol}{Constants.SymbolDot}")) { return($"{Constants.SQLJoinSymbol} x {Constants.SQLInSymbol} {navigationPath}"); } return($"{Constants.SQLJoinSymbol} x {Constants.SQLInSymbol} {Constants.SQLFieldNameSymbol}{Constants.SymbolDot}{navigationPath}"); }
private Expression Lambda(CollectionNavigationNode sourceNode, SingleValueNode body, String methodName) { Expression source = TranslateNode(sourceNode); PropertyInfo sourceNavigationProperty = Parameter.Type.GetProperty(sourceNode.NavigationProperty.Name); Type targetType = OeExpressionHelper.GetCollectionItemType(sourceNavigationProperty.PropertyType); ParameterExpression parameter = Expression.Parameter(targetType); Expression bodyExression = new OeQueryNodeVisitor(this, parameter).TranslateNode(body); LambdaExpression lambda = Expression.Lambda(bodyExression, parameter); return(Expression.Call(typeof(Enumerable), methodName, new Type[] { targetType }, source, lambda)); }
private static List <string> GetReferencePath(this List <string> list, CollectionNavigationNode navigationNode) { switch (navigationNode.Source) { case SingleNavigationNode sourceNode: list.GetReferencePath(sourceNode); list.AddRange(navigationNode.BindingPath.PathSegments); return(list); default: list.AddRange(navigationNode.BindingPath.PathSegments); return(list); } }
/// <summary> /// Translate a CollectionNavigationNode. /// </summary> /// <param name="nodeIn">The node to be translated.</param> /// <returns>The translated node.</returns> public override QueryNode Visit(CollectionNavigationNode nodeIn) { if (nodeIn == null) { throw Error.ArgumentNull(nameof(nodeIn)); } return(nodeIn.Source == null ? nodeIn : new CollectionNavigationNode( (SingleResourceNode)nodeIn.Source.Accept(this), nodeIn.NavigationProperty, nodeIn.BindingPath ?? new EdmPathExpression(nodeIn.NavigationProperty.Name))); }
private void ValidateCollectionNode(CollectionNode node, ODataValidationSettings settings) { switch (node.Kind) { case QueryNodeKind.CollectionPropertyAccess: CollectionPropertyAccessNode propertyAccessNode = node as CollectionPropertyAccessNode; ValidateCollectionPropertyAccessNode(propertyAccessNode, settings); break; case QueryNodeKind.CollectionNavigationNode: CollectionNavigationNode navigationNode = node as CollectionNavigationNode; ValidateNavigationPropertyNode(navigationNode.Source, navigationNode.NavigationProperty, settings); break; } }
/// <summary> /// Write collection navigation node to string. /// </summary> /// <param name="node">Node to write to string</param> /// <returns>String representation of node.</returns> private static string ToString(CollectionNavigationNode node) { if (node != null) { return(tabHelper.Prefix + "CollectionNavigationNode" + tabHelper.Indent(() => tabHelper.Prefix + "ItemType = " + node.ItemType + tabHelper.Prefix + "Entity Item Type = " + node.EntityItemType + tabHelper.Prefix + "NavigationSource = " + node.NavigationSource.Name + tabHelper.Prefix + "Multiplicity = " + node.TargetMultiplicity + tabHelper.Prefix + "Navigation Property = " + node.NavigationProperty.Name + tabHelper.Prefix + "Source = " + ToString(node.Source) )); } return(String.Empty); }
private void TestNavigation <TParam, TReturn>(SingleEntityNode source, IEdmNavigationProperty navigation, Expression <Func <TParam, TReturn> > expectedExpression) { QueryNode node; if (navigation.Type.IsCollection()) { node = new CollectionNavigationNode(navigation, source); } else { node = new SingleNavigationNode(navigation, source); } var result = this.testSubject.TranslateNode(node); CompareExpressions(expectedExpression.Body, result); }
private Expression Lambda(CollectionNavigationNode sourceNode, SingleValueNode body, String methodName) { Expression source = TranslateNode(sourceNode); PropertyInfo sourceNavigationProperty = Parameter.Type.GetProperty(sourceNode.NavigationProperty.Name); Type targetType = OeExpressionHelper.GetCollectionItemType(sourceNavigationProperty.PropertyType); ParameterExpression it = Expression.Parameter(targetType); _parameters.Push(it); var bodyExression = TranslateNode(body); _parameters.Pop(); LambdaExpression lambda = Expression.Lambda(bodyExression, it); var typeArguments = new Type[] { it.Type }; return(Expression.Call(typeof(Enumerable), methodName, typeArguments, source, lambda)); }
private static string GetNavigationPath(CollectionNavigationNode nodeIn) { if (nodeIn.NavigationSource == null) { return(nodeIn.NavigationProperty.Name); } string[] pathSegments; if (nodeIn.Source.Kind == QueryNodeKind.SingleComplexNode) { var paths = GetPathFromSource(nodeIn.Source as SingleComplexNode); paths.Add(nodeIn.NavigationProperty.Name); pathSegments = paths.ToArray(); } else { pathSegments = nodeIn.NavigationSource.Path.PathSegments.Skip(1).ToArray(); } var path = string.Join(Constants.SymbolDot, pathSegments); return(string.IsNullOrWhiteSpace(path) ? string.Empty : path); }
/// <summary> /// Write collection navigation node to string. /// </summary> /// <param name="node">Node to write to string</param> /// <returns>String representation of node.</returns> private static string ToString(CollectionNavigationNode node) { if (node != null) { return tabHelper.Prefix + "CollectionNavigationNode" + tabHelper.Indent(() => tabHelper.Prefix + "ItemType = " + node.ItemType + tabHelper.Prefix + "Entity Item Type = " + node.EntityItemType + tabHelper.Prefix + "NavigationSource = " + node.NavigationSource.Name + tabHelper.Prefix + "Multiplicity = " + node.TargetMultiplicity + tabHelper.Prefix + "Navigation Property = " + node.NavigationProperty.Name + tabHelper.Prefix + "Source = " + ToString(node.Source) ); } return String.Empty; }
/// <summary> /// Builds an appropriate navigation query node (collection or single) for the given property and parent node. /// </summary> /// <param name="property">Navigation property.</param> /// <param name="parent">Parent Node.</param> /// <param name="namedValues">Named values (key values) that were included in the node we are binding, if any.</param> /// <param name="state">State of binding.</param> /// <param name="keyBinder">Object to perform binding on any key values that are present.</param> /// <returns>A new CollectionNavigationNode or SingleNavigationNode to capture the navigation propety access.</returns> internal static QueryNode GetNavigationNode(IEdmNavigationProperty property, SingleEntityNode parent, IEnumerable<NamedValue> namedValues, BindingState state, KeyBinder keyBinder) { ExceptionUtils.CheckArgumentNotNull(property, "property"); ExceptionUtils.CheckArgumentNotNull(parent, "parent"); ExceptionUtils.CheckArgumentNotNull(state, "state"); ExceptionUtils.CheckArgumentNotNull(keyBinder, "keyBinder"); // Handle collection navigation property if (property.TargetMultiplicity() == EdmMultiplicity.Many) { CollectionNavigationNode collectionNavigationNode = new CollectionNavigationNode(property, parent); // Doing key lookup on the collection navigation property if (namedValues != null) { return keyBinder.BindKeyValues(collectionNavigationNode, namedValues, state.Model); } // Otherwise it's just a normal collection of entities return collectionNavigationNode; } Debug.Assert(namedValues == null || !namedValues.Any(), "namedValues should not exist if it isn't a colleciton"); // Otherwise it's a single navigation property return new SingleNavigationNode(property, parent); }
public void CollectionNavigationNodeHandlesNullSourceSetParameter() { var collectionCastNode = new CollectionNavigationNode(HardCodedTestModel.GetDogMyPeopleNavProp(), (IEdmNavigationSource)null); collectionCastNode.NavigationSource.Should().BeNull(); }
/// <summary> /// Compares collection navigation 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(CollectionNavigationNode left, CollectionNavigationNode right) { if (left.ItemType != right.ItemType) return false; if (left.EntityItemType != right.EntityItemType) return false; if (left.NavigationSource != right.NavigationSource) return false; if (left.TargetMultiplicity != right.TargetMultiplicity) return false; if (left.NavigationProperty != right.NavigationProperty) return false; return this.Compare(left.Source, right.Source); }
public void CollectionNavigationNodeOnSingletonShouldWork() { var collectionCastNode = new CollectionNavigationNode(HardCodedTestModel.GetPersonMyPaintingsNavProp(), HardCodedTestModel.GetBossSingleton()); collectionCastNode.NavigationSource.Should().Be(HardCodedTestModel.GetPaintingsSet()); }
private static void BuildFilterWithNestedAny() { var personTypeRef = new EdmEntityTypeReference(TripPinModel.Person, false); var tripTypeRef = new EdmEntityTypeReference(TripPinModel.Trip, false); var friendsProp = (IEdmNavigationProperty)TripPinModel.Person.FindProperty("Friends"); var tripsProp = (IEdmNavigationProperty)TripPinModel.Person.FindProperty("Trips"); var budgetProp = TripPinModel.Trip.FindProperty("Budget"); var topIt = new EntityRangeVariable("$it", personTypeRef, TripPinModel.PeopleSet); var topItRef = new EntityRangeVariableReferenceNode("$it", topIt); var friendsNavNode0 = new CollectionNavigationNode(friendsProp, topItRef); var e0 = new EntityRangeVariable("e0", personTypeRef, friendsNavNode0); var e0Ref = new EntityRangeVariableReferenceNode("e0", e0); var friendsNavNode1 = new CollectionNavigationNode(friendsProp, e0Ref); var e1 = new EntityRangeVariable("e1", personTypeRef, friendsNavNode1); var e1Ref = new EntityRangeVariableReferenceNode("e1", e1); var tripNavNode = new CollectionNavigationNode(tripsProp, e1Ref); var e2 = new EntityRangeVariable("e2", tripTypeRef, friendsNavNode1); var e2Ref = new EntityRangeVariableReferenceNode("e2", e2); var bugetNode = new SingleValuePropertyAccessNode(e2Ref, budgetProp); var gt = new BinaryOperatorNode( BinaryOperatorKind.GreaterThan, bugetNode, new ConstantNode(1200, "1200")); var any2 = new AnyNode(new Collection<RangeVariable> { e2 }, e2) { Body = gt, Source = tripNavNode }; var any1 = new AnyNode(new Collection<RangeVariable> { e1 }, e1) { Body = any2, Source = friendsNavNode1 }; var any0 = new AnyNode(new Collection<RangeVariable> { e0 }, e0) { Body = any1, Source = friendsNavNode0 }; var odataUri = new ODataUri { Path = new ODataPath(new EntitySetSegment(TripPinModel.PeopleSet)), ServiceRoot = TripPinRoot, Filter = new FilterClause(any0, topIt) }; var builder = new ODataUriBuilder(ODataUrlConventions.Default, odataUri); Console.WriteLine(builder.BuildUri()); // http://services.odata.org/V4/TripPinService/People?$filter=Friends%2Fany(e0:e0%2FFriends%2Fany(e1:e1%2FTrips%2Fany(e2:e2%2FBudget gt 1200))) }