/// <summary> /// Checks whether a query node is a collection query node representing a collection of entities. /// </summary> /// <param name="query">The <see cref="QueryNode"/> to check.</param> /// <returns>The converted <see cref="CollectionQueryNode"/> or null if <paramref name="query"/> is not an entity collection node.</returns> internal static CollectionQueryNode AsEntityCollectionNode(this QueryNode query) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(query != null, "query != null"); CollectionQueryNode collectionNode = query as CollectionQueryNode; if (collectionNode != null && collectionNode.ItemType != null && collectionNode.ItemType.IsODataEntityTypeKind()) { return(collectionNode); } return(null); }
/// <summary> /// Binds key values to a key lookup on a collection. /// </summary> /// <param name="collectionQueryNode">Already bound collection node.</param> /// <param name="namedValues">The named value tokens to bind.</param> /// <returns>The bound key lookup.</returns> private QueryNode BindKeyValues(CollectionQueryNode collectionQueryNode, IEnumerable<NamedValue> namedValues) { Debug.Assert(namedValues != null, "namedValues != null"); Debug.Assert(collectionQueryNode != null, "collectionQueryNode != null"); Debug.Assert(collectionQueryNode.ItemType != null, "collectionQueryNode.ItemType != null"); IEdmTypeReference collectionItemType = collectionQueryNode.ItemType; List<KeyPropertyValue> keyPropertyValues = new List<KeyPropertyValue>(); if (!collectionItemType.IsODataEntityTypeKind()) { throw new ODataException(Strings.MetadataBinder_KeyValueApplicableOnlyToEntityType(collectionItemType.ODataFullName())); } IEdmEntityTypeReference collectionItemEntityTypeReference = collectionItemType.AsEntityOrNull(); Debug.Assert(collectionItemEntityTypeReference != null, "collectionItemEntityTypeReference != null"); IEdmEntityType collectionItemEntityType = collectionItemEntityTypeReference.EntityDefinition(); HashSet<string> keyPropertyNames = new HashSet<string>(StringComparer.Ordinal); foreach (NamedValue namedValue in namedValues) { KeyPropertyValue keyPropertyValue = this.BindKeyPropertyValue(namedValue, collectionItemEntityType); Debug.Assert(keyPropertyValue != null, "keyPropertyValue != null"); Debug.Assert(keyPropertyValue.KeyProperty != null, "keyPropertyValue.KeyProperty != null"); if (!keyPropertyNames.Add(keyPropertyValue.KeyProperty.Name)) { throw new ODataException(Strings.MetadataBinder_DuplicitKeyPropertyInKeyValues(keyPropertyValue.KeyProperty.Name)); } keyPropertyValues.Add(keyPropertyValue); } if (keyPropertyValues.Count == 0) { // No key values specified, for example '/Customers()', do not include the key lookup at all return collectionQueryNode; } else if (keyPropertyValues.Count != collectionItemEntityType.Key().Count()) { throw new ODataException(Strings.MetadataBinder_NotAllKeyPropertiesSpecifiedInKeyValues(collectionQueryNode.ItemType.ODataFullName())); } else { return new KeyLookupQueryNode() { Collection = collectionQueryNode, KeyPropertyValues = new ReadOnlyCollection<KeyPropertyValue>(keyPropertyValues) }; } }
private Expression Bind(QueryNode node) { CollectionQueryNode collectionNode = node as CollectionQueryNode; SingleValueQueryNode singleValueNode = node as SingleValueQueryNode; IncrementBindCount(); if (collectionNode != null) { switch (node.Kind) { case QueryNodeKind.Filter: return(BindFilterQueryNode(node as FilterQueryNode)); case QueryNodeKind.Segment: CollectionNavigationNode navigationNode = node as CollectionNavigationNode; return(BindNavigationPropertyNode(navigationNode.Source, navigationNode.NavigationProperty())); default: throw Error.NotSupported(SRResources.QueryNodeBindingNotSupported, node.Kind, typeof(FilterBinder).Name); } } else if (singleValueNode != null) { switch (node.Kind) { case QueryNodeKind.BinaryOperator: return(BindBinaryOperatorQueryNode(node as BinaryOperatorQueryNode)); case QueryNodeKind.Constant: return(BindConstantQueryNode(node as ConstantQueryNode)); case QueryNodeKind.Convert: return(BindConvertQueryNode(node as ConvertQueryNode)); case QueryNodeKind.Parameter: return(BindParameterQueryNode(node as ParameterQueryNode)); case QueryNodeKind.PropertyAccess: return(BindPropertyAccessQueryNode(node as PropertyAccessQueryNode)); case QueryNodeKind.UnaryOperator: return(BindUnaryOperatorQueryNode(node as UnaryOperatorQueryNode)); case QueryNodeKind.SingleValueFunctionCall: return(BindSingleValueFunctionCallQueryNode(node as SingleValueFunctionCallQueryNode)); case QueryNodeKind.Segment: SingletonNavigationNode navigationNode = node as SingletonNavigationNode; return(BindNavigationPropertyNode(navigationNode.Source, navigationNode.NavigationProperty)); case QueryNodeKind.Any: return(BindAnyQueryNode(node as AnyQueryNode)); case QueryNodeKind.All: return(BindAllQueryNode(node as AllQueryNode)); default: throw Error.NotSupported(SRResources.QueryNodeBindingNotSupported, node.Kind, typeof(FilterBinder).Name); } } else { throw Error.NotSupported(SRResources.QueryNodeBindingNotSupported, node.Kind, typeof(FilterBinder).Name); } }