/// <summary> /// Constructs a KeyLookupNode. /// </summary> /// <param name="source">The collection that this key is referring to.</param> /// <param name="keyPropertyValues">List of the properties and their values that we use to look up our return value.</param> /// <exception cref="System.ArgumentNullException">Throws if the input source is null.</exception> public KeyLookupNode(EntityCollectionNode source, IEnumerable<KeyPropertyValue> keyPropertyValues) { ExceptionUtils.CheckArgumentNotNull(source, "source"); this.source = source; this.navigationSource = source.NavigationSource; this.entityTypeReference = source.EntityItemType; this.keyPropertyValues = keyPropertyValues; }
/// <summary> /// Constructs a KeyLookupNode. /// </summary> /// <param name="source">The collection that this key is referring to.</param> /// <param name="keyPropertyValues">List of the properties and their values that we use to look up our return value.</param> /// <exception cref="System.ArgumentNullException">Throws if the input source is null.</exception> public KeyLookupNode(EntityCollectionNode source, IEnumerable <KeyPropertyValue> keyPropertyValues) { ExceptionUtils.CheckArgumentNotNull(source, "source"); this.source = source; this.navigationSource = source.NavigationSource; this.entityTypeReference = source.EntityItemType; this.keyPropertyValues = keyPropertyValues; }
/// <summary> /// Creates a <see cref="EntityRangeVariable"/>. /// </summary> /// <param name="name"> The name of the associated any/all parameter (null if none)</param> /// <param name="entityType">The entity type of each item in the collection that this range variable iterates over.</param> /// <param name="navigationSource">The navigation source of the collection this node iterates over.</param> /// <exception cref="System.ArgumentNullException">Throws if the input name or entityType is null.</exception> public EntityRangeVariable(string name, IEdmEntityTypeReference entityType, IEdmNavigationSource navigationSource) { ExceptionUtils.CheckArgumentNotNull(name, "name"); ExceptionUtils.CheckArgumentNotNull(entityType, "entityType"); this.name = name; this.entityTypeReference = entityType; this.entityCollectionNode = null; this.navigationSource = navigationSource; }
/// <summary> /// Create a CollectionCastNode with the given source node and the given target type. /// </summary> /// <param name="source">Parent <see cref="CollectionNode"/> that is being cast.</param> /// <param name="entityType">Type to cast to.</param> /// <exception cref="System.ArgumentNullException">Throws if the input source or entityType are null.</exception> public EntityCollectionCastNode(EntityCollectionNode source, IEdmEntityType entityType) { ExceptionUtils.CheckArgumentNotNull(source, "source"); ExceptionUtils.CheckArgumentNotNull(entityType, "entityType"); this.source = source; this.edmTypeReference = new EdmEntityTypeReference(entityType, false); this.navigationSource = source.NavigationSource; // creating a new collection type here because the type in the request is just the item type, there is no user-provided collection type. this.collectionTypeReference = EdmCoreModel.GetCollection(this.edmTypeReference); }
/// <summary> /// Tries to bind key values to a key lookup on a collection. /// </summary> /// <param name="collectionNode">Already bound collection node.</param> /// <param name="namedValues">The named value tokens to bind.</param> /// <param name="model">The model to be used.</param> /// <param name="collectionItemEntityType">The type of a single item in a collection to apply the key value to.</param> /// <param name="keyLookupNode">The bound key lookup.</param> /// <returns>Returns true if binding succeeded.</returns> private bool TryBindToDeclaredAlternateKey(EntityCollectionNode collectionNode, IEnumerable<NamedValue> namedValues, IEdmModel model, IEdmEntityType collectionItemEntityType, out QueryNode keyLookupNode) { IEnumerable<IDictionary<string, IEdmProperty>> alternateKeys = model.GetAlternateKeysAnnotation(collectionItemEntityType); foreach (IDictionary<string, IEdmProperty> keys in alternateKeys) { if (TryBindToKeys(collectionNode, namedValues, model, collectionItemEntityType, keys, out keyLookupNode)) { return true; } } keyLookupNode = null; return false; }
/// <summary> /// Binds key values to a key lookup on a collection. /// </summary> /// <param name="collectionNode">Already bound collection node.</param> /// <param name="namedValues">The named value tokens to bind.</param> /// <param name="model">The model to be used.</param> /// <returns>The bound key lookup.</returns> internal QueryNode BindKeyValues(EntityCollectionNode collectionNode, IEnumerable<NamedValue> namedValues, IEdmModel model) { Debug.Assert(namedValues != null, "namedValues != null"); Debug.Assert(collectionNode != null, "CollectionNode != null"); Debug.Assert(model != null, "model != null"); IEdmEntityTypeReference collectionItemType = collectionNode.EntityItemType; IEdmEntityType collectionItemEntityType = collectionItemType.EntityDefinition(); QueryNode keyLookupNode; if (TryBindToDeclaredKey(collectionNode, namedValues, model, collectionItemEntityType, out keyLookupNode)) { return keyLookupNode; } else if (TryBindToDeclaredAlternateKey(collectionNode, namedValues, model, collectionItemEntityType, out keyLookupNode)) { return keyLookupNode; } else { throw new ODataException(ODataErrorStrings.MetadataBinder_NotAllKeyPropertiesSpecifiedInKeyValues(collectionNode.ItemType.FullName())); } }
/// <summary> /// Binds key values to a key lookup on a collection. /// </summary> /// <param name="collectionNode">Already bound collection node.</param> /// <param name="namedValues">The named value tokens to bind.</param> /// <param name="model">The model to be used.</param> /// <param name="collectionItemEntityType">The type of a single item in a collection to apply the key value to.</param> /// <param name="keys">Dictionary of aliases to structural property names for the key.</param> /// <param name="keyLookupNode">The bound key lookup.</param> /// <returns>Returns true if binding succeeded.</returns> private bool TryBindToKeys(EntityCollectionNode collectionNode, IEnumerable<NamedValue> namedValues, IEdmModel model, IEdmEntityType collectionItemEntityType, IDictionary<string, IEdmProperty> keys, out QueryNode keyLookupNode) { List<KeyPropertyValue> keyPropertyValues = new List<KeyPropertyValue>(); HashSet<string> keyPropertyNames = new HashSet<string>(StringComparer.Ordinal); foreach (NamedValue namedValue in namedValues) { KeyPropertyValue keyPropertyValue; if (!this.TryBindKeyPropertyValue(namedValue, collectionItemEntityType, keys, out keyPropertyValue)) { keyLookupNode = null; return false; } Debug.Assert(keyPropertyValue != null, "keyPropertyValue != null"); Debug.Assert(keyPropertyValue.KeyProperty != null, "keyPropertyValue.KeyProperty != null"); if (!keyPropertyNames.Add(keyPropertyValue.KeyProperty.Name)) { throw new ODataException(ODataErrorStrings.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 keyLookupNode = collectionNode; return true; } else if (keyPropertyValues.Count != collectionItemEntityType.Key().Count()) { keyLookupNode = null; return false; } else { keyLookupNode = new KeyLookupNode(collectionNode, new ReadOnlyCollection<KeyPropertyValue>(keyPropertyValues)); return true; } }
/// <summary> /// Tries to bind key values to a key lookup on a collection. /// </summary> /// <param name="collectionNode">Already bound collection node.</param> /// <param name="namedValues">The named value tokens to bind.</param> /// <param name="model">The model to be used.</param> /// <param name="collectionItemEntityType">The type of a single item in a collection to apply the key value to.</param> /// <param name="keyLookupNode">The bound key lookup.</param> /// <returns>Returns true if binding succeeded.</returns> private bool TryBindToDeclaredKey(EntityCollectionNode collectionNode, IEnumerable<NamedValue> namedValues, IEdmModel model, IEdmEntityType collectionItemEntityType, out QueryNode keyLookupNode) { Dictionary<string, IEdmProperty> keys = new Dictionary<string, IEdmProperty>(StringComparer.Ordinal); foreach (IEdmStructuralProperty property in collectionItemEntityType.Key()) { keys[property.Name] = property; } return TryBindToKeys(collectionNode, namedValues, model, collectionItemEntityType, keys, out keyLookupNode); }