/// <summary> /// Binds a key property value. /// </summary> /// <param name="namedValue">The named value to bind.</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 alias to keys.</param> /// <param name="keyPropertyValue">The bound key property value node.</param> /// <returns>The bound key property value node.</returns> private bool TryBindKeyPropertyValue(NamedValue namedValue, IEdmEntityType collectionItemEntityType, IDictionary <string, IEdmProperty> keys, out KeyPropertyValue keyPropertyValue) { // These are exception checks because the data comes directly from the potentially user specified tree. ExceptionUtils.CheckArgumentNotNull(namedValue, "namedValue"); ExceptionUtils.CheckArgumentNotNull(namedValue.Value, "namedValue.Value"); Debug.Assert(collectionItemEntityType != null, "collectionItemType != null"); IEdmProperty keyProperty = null; if (namedValue.Name == null) { foreach (IEdmProperty p in keys.Values) { if (keyProperty == null) { keyProperty = p; } else { throw new ODataException(ODataErrorStrings.MetadataBinder_UnnamedKeyValueOnTypeWithMultipleKeyProperties(collectionItemEntityType.FullTypeName())); } } } else { keyProperty = keys.SingleOrDefault(k => string.CompareOrdinal(k.Key, namedValue.Name) == 0).Value; if (keyProperty == null) { keyPropertyValue = null; return(false); } } IEdmTypeReference keyPropertyType = keyProperty.Type; SingleValueNode value = (SingleValueNode)this.keyValueBindMethod(namedValue.Value); // TODO: Check that the value is of primitive type Debug.Assert(keyPropertyType.IsODataPrimitiveTypeKind(), "The key's type must be primitive."); value = MetadataBindingUtils.ConvertToTypeIfNeeded(value, keyPropertyType); Debug.Assert(keyProperty != null, "keyProperty != null"); keyPropertyValue = new KeyPropertyValue() { KeyProperty = keyProperty, KeyValue = value }; return(true); }
/// <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> /// <returns>The bound key lookup.</returns> internal QueryNode BindKeyValues(EntityCollectionNode collectionNode, IEnumerable <NamedValue> namedValues) { Debug.Assert(namedValues != null, "namedValues != null"); Debug.Assert(collectionNode != null, "CollectionNode != null"); IEdmEntityTypeReference collectionItemType = collectionNode.EntityItemType; List <KeyPropertyValue> keyPropertyValues = new List <KeyPropertyValue>(); IEdmEntityType collectionItemEntityType = collectionItemType.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(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 return(collectionNode); } else if (keyPropertyValues.Count != collectionItemEntityType.Key().Count()) { throw new ODataException(ODataErrorStrings.MetadataBinder_NotAllKeyPropertiesSpecifiedInKeyValues(collectionNode.ItemType.ODataFullName())); } else { return(new KeyLookupNode(collectionNode, new ReadOnlyCollection <KeyPropertyValue>(keyPropertyValues))); } }
/// <summary> /// Binds a key property value. /// </summary> /// <param name="namedValue">The named value to bind.</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 alias to keys.</param> /// <param name="keyPropertyValue">The bound key property value node.</param> /// <returns>The bound key property value node.</returns> private bool TryBindKeyPropertyValue(NamedValue namedValue, IEdmEntityType collectionItemEntityType, IDictionary<string, IEdmProperty> keys, out KeyPropertyValue keyPropertyValue) { // These are exception checks because the data comes directly from the potentially user specified tree. ExceptionUtils.CheckArgumentNotNull(namedValue, "namedValue"); ExceptionUtils.CheckArgumentNotNull(namedValue.Value, "namedValue.Value"); Debug.Assert(collectionItemEntityType != null, "collectionItemType != null"); IEdmProperty keyProperty = null; if (namedValue.Name == null) { foreach (IEdmProperty p in keys.Values) { if (keyProperty == null) { keyProperty = p; } else { throw new ODataException(ODataErrorStrings.MetadataBinder_UnnamedKeyValueOnTypeWithMultipleKeyProperties(collectionItemEntityType.FullTypeName())); } } } else { keyProperty = keys.SingleOrDefault(k => string.CompareOrdinal(k.Key, namedValue.Name) == 0).Value; if (keyProperty == null) { keyPropertyValue = null; return false; } } IEdmTypeReference keyPropertyType = keyProperty.Type; SingleValueNode value = (SingleValueNode)this.keyValueBindMethod(namedValue.Value); // TODO: Check that the value is of primitive type Debug.Assert(keyPropertyType.IsODataPrimitiveTypeKind(), "The key's type must be primitive."); value = MetadataBindingUtils.ConvertToTypeIfNeeded(value, keyPropertyType); Debug.Assert(keyProperty != null, "keyProperty != null"); keyPropertyValue = new KeyPropertyValue() { KeyProperty = keyProperty, KeyValue = value }; return true; }
public static string ToDebugString(this KeyPropertyValue keyPropertyValue) { return(keyPropertyValue.KeyProperty.Name + "=" + keyPropertyValue.KeyValue.ToDebugString()); }