/// <summary> /// Creates metadata properties for the specified enumeration of OData OM properties. /// </summary> /// <param name="model">The model to use.</param> /// <param name="owningType">The owning type to which to add the properties.</param> /// <param name="properties">Enumeration of the properties to add.</param> private static void CreateMetadataProperties(EntityModelSchema model, NamedStructuralType owningType, IEnumerable<ODataProperty> properties) { if (properties == null) { return; } foreach (ODataProperty property in properties) { ODataPropertyMetadataAnnotation propertyMetadataAnnotation = property.GetInheritedAnnotation<ODataPropertyMetadataAnnotation>(); object propertyValue = property.Value; bool isOpenProperty = false; if (propertyMetadataAnnotation != null) { isOpenProperty = propertyMetadataAnnotation.IsOpenProperty; ExceptionUtilities.Assert( !isOpenProperty || owningType is EntityType, "Can't declare an open property on non-entity type."); if (propertyMetadataAnnotation.PropertyValueForTypeInference != null) { propertyValue = propertyMetadataAnnotation.PropertyValueForTypeInference; } } ODataComplexValue complexValue = propertyValue as ODataComplexValue; if (complexValue != null) { ExceptionUtilities.Assert(complexValue.TypeName.StartsWith(owningType.NamespaceName + "."), "The type name must start with the same namespace as its owning type."); ComplexType complexType = model.GetComplexType(complexValue.TypeName); if (complexType == null) { string complexTypeLocalName = complexValue.TypeName.Substring(owningType.NamespaceName.Length + 1); complexType = model.ComplexType(complexTypeLocalName, owningType.NamespaceName); CreateMetadataProperties(model, complexType, complexValue.Properties); } if (isOpenProperty) { owningType.IsOpen = true; } else { owningType.Property(property.Name, DataTypes.ComplexType.WithDefinition(complexType).Nullable()); } } else { bool isKeyProperty = false; bool isETagProperty = false; if (propertyMetadataAnnotation != null) { isKeyProperty = (propertyMetadataAnnotation.Kind & ODataPropertyKind.Key) == ODataPropertyKind.Key; isETagProperty = (propertyMetadataAnnotation.Kind & ODataPropertyKind.ETag) == ODataPropertyKind.ETag; ExceptionUtilities.Assert( !isKeyProperty || owningType is EntityType, "Can't declare a key property on non-entity type."); ExceptionUtilities.Assert( !isETagProperty || owningType is EntityType, "Can't declare an etag property on non-entity type."); ExceptionUtilities.Assert( !isOpenProperty || !(isKeyProperty || isETagProperty), "Key or etag property can't be open."); } if (owningType is EntityType && isOpenProperty) { owningType.IsOpen = true; } else { EntityType owningEntityType = owningType as EntityType; if (owningEntityType != null && isKeyProperty) { ExceptionUtilities.Assert( propertyValue != null, "Found a key property with null value, can't infer type from value in that case and it's invalid anyway."); PrimitiveDataType keyPropertyType = EntityModelUtils.GetPrimitiveEdmType(propertyValue.GetType()); owningEntityType.KeyProperty(property.Name, keyPropertyType, isETagProperty); } else { if (propertyValue is ODataCollectionValue) { string itemTypeName = EntityModelUtils.GetCollectionItemTypeName(((ODataCollectionValue)propertyValue).TypeName); CollectionDataType collectionType = null; DataType primitiveItemType = EntityModelUtils.GetPrimitiveEdmType(itemTypeName); if (primitiveItemType != null) { collectionType = DataTypes.CollectionType.WithElementDataType(primitiveItemType); } else { ComplexType complexItemType = model.GetComplexType(itemTypeName); collectionType = DataTypes.CollectionOfComplex(complexItemType); } ExceptionUtilities.Assert(collectionType != null, "Could not resolve item type."); owningType.Property(property.Name, collectionType); } else { Type propertyType = propertyValue == null ? typeof(string) : propertyValue.GetType(); PrimitiveDataType edmPropertyType = EntityModelUtils.GetPrimitiveEdmType(propertyType); owningType.Property(property.Name, edmPropertyType, isETagProperty); } } } } } }