/// <summary> /// Validates the type of an entry in a top-level feed. /// </summary> /// <param name="entityType">The type of the entry.</param> internal void ValidateEntry(IEdmEntityType entityType) { Debug.Assert(entityType != null, "entityType != null"); // If we don't have a type, store the type of the first item. if (this.itemType == null) { this.itemType = entityType; } // Validate the expected and actual types. if (this.itemType.IsEquivalentTo(entityType)) { return; } // If the types are not equivalent, make sure they have a common base type. IEdmType commonBaseType = EdmLibraryExtensions.GetCommonBaseType(this.itemType, entityType); if (commonBaseType == null) { throw new ODataException(Strings.FeedWithoutExpectedTypeValidator_IncompatibleTypes(entityType.FullTypeName(), this.itemType.FullTypeName())); } this.itemType = (IEdmEntityType)commonBaseType; }
public void CreateEdmTypeSchemaReturnSchemaForEntityType(bool isNullable, OpenApiSpecVersion specVersion) { // Arrange IEdmModel model = EdmModelHelper.TripServiceModel; IEdmEntityType entity = model.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "Manager"); Assert.NotNull(entity); // guard IEdmEntityTypeReference entityTypeReference = new EdmEntityTypeReference(entity, isNullable); ODataContext context = new ODataContext(model); context.Settings.OpenApiSpecVersion = specVersion; // Act var schema = context.CreateEdmTypeSchema(entityTypeReference); // & Assert Assert.NotNull(schema); if (specVersion == OpenApiSpecVersion.OpenApi2_0 || isNullable == false) { Assert.Null(schema.AnyOf); Assert.NotNull(schema.Reference); Assert.Equal(ReferenceType.Schema, schema.Reference.Type); Assert.Equal(entity.FullTypeName(), schema.Reference.Id); } else { Assert.Null(schema.Reference); Assert.NotNull(schema.AnyOf); Assert.NotEmpty(schema.AnyOf); var anyOf = Assert.Single(schema.AnyOf); Assert.NotNull(anyOf.Reference); Assert.Equal(ReferenceType.Schema, anyOf.Reference.Type); Assert.Equal(entity.FullTypeName(), anyOf.Reference.Id); } }
/// <summary> /// If an entity type name is found in the payload this method is called to apply it to the current scope. /// This method should be called even if the type name was not found in which case a null should be passed in. /// The method validates that some type will be available as the current entity type after it returns (if we are parsing using metadata). /// </summary> /// <param name="entityTypeNameFromPayload">The entity type name found in the payload or null if no type was specified in the payload.</param> protected void ApplyEntityTypeNameFromPayload(string entityTypeNameFromPayload) { Debug.Assert( this.scopes.Count > 0 && this.scopes.Peek().Item is ODataEntry, "Entity type can be applied only when in entry scope."); SerializationTypeNameAnnotation serializationTypeNameAnnotation; EdmTypeKind targetTypeKind; IEdmEntityTypeReference targetEntityTypeReference = (IEdmEntityTypeReference)ReaderValidationUtils.ResolvePayloadTypeNameAndComputeTargetType( EdmTypeKind.Entity, /*defaultPrimitivePayloadType*/ null, this.CurrentEntityType.ToTypeReference(), entityTypeNameFromPayload, this.inputContext.Model, this.inputContext.MessageReaderSettings, () => EdmTypeKind.Entity, out targetTypeKind, out serializationTypeNameAnnotation); IEdmEntityType targetEntityType = null; ODataEntry entry = this.CurrentEntry; if (targetEntityTypeReference != null) { targetEntityType = targetEntityTypeReference.EntityDefinition(); entry.TypeName = targetEntityType.FullTypeName(); if (serializationTypeNameAnnotation != null) { entry.SetAnnotation(serializationTypeNameAnnotation); } } else if (entityTypeNameFromPayload != null) { entry.TypeName = entityTypeNameFromPayload; } // Set the current entity type since the type from payload might be more derived than // the expected one. this.CurrentEntityType = targetEntityType; }
private void VisitEntityType(IEdmEntityType entity) { string qualifiedName = entity.FullTypeName(); if (_types.ContainsKey(qualifiedName)) { return; // processed } MetaEntityType metaEntity = new MetaEntityType(); metaEntity.QualifiedName = qualifiedName; metaEntity.Name = entity.Name; metaEntity.Abstract = entity.IsAbstract; metaEntity.OpenType = entity.IsOpen; metaEntity.HasStream = entity.HasStream; _types[qualifiedName] = metaEntity; VisitProperties(metaEntity, entity.DeclaredProperties); VisitNavProperties(metaEntity, entity.DeclaredNavigationProperties()); }
/// <summary> /// Translate NavigationPropertySegment to linq expression. /// </summary> /// <param name="segment">The NavigationPropertySegment</param> /// <returns>The linq expression</returns> public override Expression Translate(NavigationPropertySegment segment) { if (!(this.LastProcessedSegment is KeySegment || this.LastProcessedSegment is SingletonSegment || this.LastProcessedSegment is TypeSegment || this.LastProcessedSegment is NavigationPropertySegment)) { throw new InvalidOperationException("Unsupported URI segment before NavigationPropertySegment"); } IEdmEntityType lastSegmentEntityType = this.LastProcessedSegment.EdmType as IEdmEntityType; IEdmNavigationProperty navigationProperty = segment.NavigationProperty; // <context>/PropertyName will be translated to <context>.PropertyName Type sourceInstanceType = EdmClrTypeUtils.GetInstanceType(lastSegmentEntityType.FullTypeName()); this.ResultExpression = Expression.Property(this.ResultExpression, sourceInstanceType, navigationProperty.Name); this.LastProcessedSegment = segment; return(this.ResultExpression); }
/// <summary> /// Validates that the specified <paramref name="resource"/> is a valid resource as per the specified type. /// </summary> /// <param name="resource">The resource to validate.</param> /// <param name="resourceType">Optional entity type to validate the resource against.</param> /// <remarks>If the <paramref name="resourceType"/> is available only resource-level tests are performed, properties and such are not validated.</remarks> internal static void ValidateMediaResource(ODataResourceBase resource, IEdmEntityType resourceType) { Debug.Assert(resource != null, "resource != null"); if (resourceType != null) { if (resource.MediaResource == null) { if (resourceType.HasStream) { throw new ODataException(Strings.ValidationUtils_ResourceWithoutMediaResourceAndMLEType(resourceType.FullTypeName())); } } else { if (!resourceType.HasStream) { throw new ODataException(Strings.ValidationUtils_ResourceWithMediaResourceAndNonMLEType(resourceType.FullTypeName())); } } } }
/// <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> /// Validates an entry in an expanded link to make sure the entity types match. /// </summary> /// <param name="entryEntityType">The <see cref="IEdmEntityType"/> of the entry.</param> /// <param name="parentNavigationPropertyType">The type of the parent navigation property.</param> internal static void ValidateEntryInExpandedLink(IEdmEntityType entryEntityType, IEdmEntityType parentNavigationPropertyType) { if (parentNavigationPropertyType == null) { return; } Debug.Assert(entryEntityType != null, "If we have a parent navigation property type we should also have an entry type."); // Make sure the entity types are compatible if (!parentNavigationPropertyType.IsAssignableFrom(entryEntityType)) { throw new ODataException(Strings.WriterValidationUtils_EntryTypeInExpandedLinkNotCompatibleWithNavigationPropertyType(entryEntityType.FullTypeName(), parentNavigationPropertyType.FullTypeName())); } }
/// <summary> /// Validates that a navigation property with the specified name exists on a given entity type. /// The entity type can be null if no metadata is available. /// </summary> /// <param name="propertyName">The name of the property to validate.</param> /// <param name="owningEntityType">The owning entity type or null if no metadata is available.</param> /// <returns>The <see cref="IEdmProperty"/> instance representing the navigation property with name <paramref name="propertyName"/> /// or null if no metadata is available.</returns> internal static IEdmNavigationProperty ValidateNavigationPropertyDefined(string propertyName, IEdmEntityType owningEntityType) { Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)"); if (owningEntityType == null) { return null; } IEdmProperty property = ValidatePropertyDefined(propertyName, owningEntityType); if (property == null) { // We don't support open navigation properties Debug.Assert(owningEntityType.IsOpen, "We should have already failed on non-existing property on a closed type."); throw new ODataException(Strings.ValidationUtils_OpenNavigationProperty(propertyName, owningEntityType.FullTypeName())); } if (property.PropertyKind != EdmPropertyKind.Navigation) { // The property must be a navigation property throw new ODataException(Strings.ValidationUtils_NavigationPropertyExpected(propertyName, owningEntityType.FullTypeName(), property.PropertyKind.ToString())); } return (IEdmNavigationProperty)property; }
/// <summary> /// Validates the <see cref="IEdmModel"/> that is being created. /// </summary> /// <param name="model">The <see cref="IEdmModel"/> that will be validated.</param> public virtual void ValidateModel(IEdmModel model) { if (model == null) { throw Error.ArgumentNull("model"); } // The type of entity set should have key(s) defined. foreach (IEdmEntitySet entitySet in model.EntityContainer.Elements.OfType <IEdmEntitySet>()) { if (!entitySet.EntityType().Key().Any()) { throw Error.InvalidOperation(SRResources.EntitySetTypeHasNoKeys, entitySet.Name, entitySet.EntityType().FullName()); } } // The type of collection navigation property should have key(s) defined. foreach (IEdmStructuredType structuredType in model.SchemaElementsAcrossModels().OfType <IEdmStructuredType>()) { foreach (var navigationProperty in structuredType.DeclaredNavigationProperties()) { if (navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many) { IEdmEntityType entityType = navigationProperty.ToEntityType(); if (!entityType.Key().Any()) { throw Error.InvalidOperation(SRResources.CollectionNavigationPropertyEntityTypeDoesntHaveKeyDefined, entityType.FullTypeName(), navigationProperty.Name, structuredType.FullTypeName()); } } } } }
/// <summary> /// Writes an OData feed. /// </summary> /// <param name="writer">The ODataWriter that will write the feed.</param> /// <param name="entityType">The type of the entity in the feed.</param> /// <param name="entries">The items from the data store to write to the feed.</param> /// <param name="entitySet">The entity set in the model that the feed belongs to.</param> /// <param name="targetVersion">The OData version this segment is targeting.</param> /// <param name="selectExpandClause">The SelectExpandClause.</param> public static void WriteFeed(ODataWriter writer, IEdmEntityType entityType, IEnumerable entries, IEdmEntitySetBase entitySet, ODataVersion targetVersion, SelectExpandClause selectExpandClause, long? count, Uri deltaLink, Uri nextPageLink, Dictionary<string, string> incomingHeaders = null) { var feed = new ODataFeed { Id = entitySet == null ? null : new Uri(ServiceConstants.ServiceBaseUri, entitySet.Name), DeltaLink = deltaLink, NextPageLink = nextPageLink }; if (entitySet == null) { feed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo() { NavigationSourceEntityTypeName = entityType.FullTypeName(), NavigationSourceName = null, NavigationSourceKind = EdmNavigationSourceKind.UnknownEntitySet, IsFromCollection = true }); } if (count.HasValue) { feed.Count = count; } writer.WriteStart(feed); foreach (var element in entries) { WriteEntry(writer, element, entitySet, targetVersion, selectExpandClause, incomingHeaders); } writer.WriteEnd(); }
/// <summary> /// Построение объекта данных по сущности OData. /// </summary> /// <param name="edmEntity"> Сущность OData. </param> /// <param name="key"> Значение ключевого поля сущности. </param> /// <param name="dObjs"> Список объектов для обновления. </param> /// <param name="endObject"> Признак, что объект добавляется в конец списка обновления. </param> /// <returns> Объект данных. </returns> private DataObject GetDataObjectByEdmEntity(EdmEntityObject edmEntity, object key, List <DataObject> dObjs, bool endObject = false) { if (edmEntity == null) { return(null); } IEdmEntityType entityType = (IEdmEntityType)edmEntity.ActualEdmType; Type objType = _model.GetDataObjectType(_model.GetEdmEntitySet(entityType).Name); // Значение свойства. object value; // Получим значение ключа. var keyProperty = entityType.Properties().FirstOrDefault(prop => prop.Name == _model.KeyPropertyName); if (key != null) { value = key; } else { edmEntity.TryGetPropertyValue(keyProperty.Name, out value); } // Загрузим объект из хранилища, если он там есть (используем представление по умолчанию), или создадим, если нет, но только для POST. // Тем самым гарантируем загруженность свойств при необходимости обновления и установку нужного статуса. DataObject obj = ReturnDataObject(objType, value); // Добавляем объект в список для обновления, если там ещё нет объекта с таким ключом. var objInList = dObjs.FirstOrDefault(o => o.__PrimaryKey.ToString() == obj.__PrimaryKey.ToString()); if (objInList == null) { if (!endObject) { // Добавляем объект в начало списка. dObjs.Insert(0, obj); } else { // Добавляем в конец списка. dObjs.Add(obj); } } // Все свойства объекта данных означим из пришедшей сущности, если они были там установлены(изменены). foreach (var prop in entityType.Properties()) { string dataObjectPropName = _model.GetDataObjectProperty(entityType.FullTypeName(), prop.Name).Name; if (edmEntity.GetChangedPropertyNames().Contains(prop.Name)) { // Обработка мастеров и детейлов. if (prop is EdmNavigationProperty) { EdmNavigationProperty navProp = (EdmNavigationProperty)prop; edmEntity.TryGetPropertyValue(prop.Name, out value); EdmMultiplicity edmMultiplicity = navProp.TargetMultiplicity(); // var aggregator = Information.GetAgregatePropertyName(objType); // Обработка мастеров. if (edmMultiplicity == EdmMultiplicity.One || edmMultiplicity == EdmMultiplicity.ZeroOrOne) { if (value != null && value is EdmEntityObject) { EdmEntityObject edmMaster = (EdmEntityObject)value; DataObject master = GetDataObjectByEdmEntity(edmMaster, null, dObjs); Information.SetPropValueByName(obj, dataObjectPropName, master); } else { Information.SetPropValueByName(obj, dataObjectPropName, null); } } // Обработка детейлов. if (edmMultiplicity == EdmMultiplicity.Many) { Type detType = Information.GetPropertyType(objType, dataObjectPropName); DetailArray detarr = (DetailArray)Information.GetPropValueByName(obj, dataObjectPropName); if (value != null && value is EdmEntityObjectCollection) { EdmEntityObjectCollection coll = (EdmEntityObjectCollection)value; if (coll != null && coll.Count > 0) { foreach (var edmEnt in coll) { DataObject det = GetDataObjectByEdmEntity( (EdmEntityObject)edmEnt, null, dObjs, true); if (det.__PrimaryKey == null) { detarr.AddObject(det); } else { detarr.SetByKey(det.__PrimaryKey, det); } } } } else { detarr.Clear(); } } } else { // Обработка собственных свойств объекта (неключевых, т.к. ключ устанавливаем при начальной инициализации объекта obj). if (prop.Name != keyProperty.Name) { Type dataObjectPropertyType = Information.GetPropertyType(objType, dataObjectPropName); edmEntity.TryGetPropertyValue(prop.Name, out value); // Если тип свойства относится к одному из зарегистрированных провайдеров файловых свойств, // значит свойство файловое, и его нужно обработать особым образом. if (FileController.HasDataObjectFileProvider(dataObjectPropertyType)) { IDataObjectFileProvider dataObjectFileProvider = FileController.GetDataObjectFileProvider(dataObjectPropertyType); // Обработка файловых свойств объектов данных. string serializedFileDescription = value as string; if (serializedFileDescription == null) { // Файловое свойство было сброшено на клиенте. // Ассоциированный файл должен быть удален, после успешного сохранения изменений. // Для этого запоминаем метаданные ассоциированного файла, до того как свойство будет сброшено // (для получения метаданных свойство будет дочитано в объект данных). // Файловое свойство типа File хранит данные ассоциированного файла прямо в БД, // соответственно из файловой системы просто нечего удалять, // поэтому обходим его стороной, чтобы избежать лишных вычиток файлов из БД. if (dataObjectPropertyType != typeof(File)) { _removingFileDescriptions.Add(dataObjectFileProvider.GetFileDescription(obj, dataObjectPropName)); } // Сбрасываем файловое свойство в изменяемом объекте данных. Information.SetPropValueByName(obj, dataObjectPropName, null); } else { // Файловое свойство было изменено, но не сброшено. // Если в метаданных файла присутствует FileUploadKey значит файл был загружен на сервер, // но еще не был ассоциирован с объектом данных, и это нужно сделать. FileDescription fileDescription = FileDescription.FromJson(serializedFileDescription); if (!(string.IsNullOrEmpty(fileDescription.FileUploadKey) || string.IsNullOrEmpty(fileDescription.FileName))) { Information.SetPropValueByName(obj, dataObjectPropName, dataObjectFileProvider.GetFileProperty(fileDescription)); // Файловое свойство типа File хранит данные ассоциированного файла прямо в БД, // поэтому после успешного сохранения объекта данных, оссоциированный с ним файл должен быть удален из файловой системы. // Для этого запоминаем описание загруженного файла. if (dataObjectPropertyType == typeof(File)) { _removingFileDescriptions.Add(fileDescription); } } } } else { // Преобразование типов для примитивных свойств. if (value is DateTimeOffset) { value = ((DateTimeOffset)value).UtcDateTime; } if (value is EdmEnumObject) { value = ((EdmEnumObject)value).Value; } Information.SetPropValueByName(obj, dataObjectPropName, value); } } } } } return(obj); }
/// <summary> /// Validates that the specified <paramref name="entry"/> is a valid entry as per the specified type. /// </summary> /// <param name="entry">The entry to validate.</param> /// <param name="entityType">Optional entity type to validate the entry against.</param> /// <param name="model">Model containing the entity type.</param> /// <param name="validateMediaResource">true if the validation of the default MediaResource should be done; false otherwise.</param> /// <remarks>If the <paramref name="entityType"/> is available only entry-level tests are performed, properties and such are not validated.</remarks> internal static void ValidateEntryMetadataResource(ODataEntry entry, IEdmEntityType entityType, IEdmModel model, bool validateMediaResource) { Debug.Assert(entry != null, "entry != null"); if (entityType != null) { Debug.Assert(model != null, "model != null"); Debug.Assert(model.IsUserModel(), "model.IsUserModel()"); if (validateMediaResource) { if (entry.MediaResource == null) { if (entityType.HasStream) { throw new ODataException(Strings.ValidationUtils_EntryWithoutMediaResourceAndMLEType(entityType.FullTypeName())); } } else { if (!entityType.HasStream) { throw new ODataException(Strings.ValidationUtils_EntryWithMediaResourceAndNonMLEType(entityType.FullTypeName())); } } } } }
/// <summary> /// Validates an entry in an expanded link to make sure the entity types match. /// </summary> /// <param name="entryEntityType">The <see cref="IEdmEntityType"/> of the entry.</param> /// <param name="parentNavigationPropertyType">The type of the parent navigation property.</param> internal static void ValidateEntryInExpandedLink(IEdmEntityType entryEntityType, IEdmEntityType parentNavigationPropertyType) { if (parentNavigationPropertyType == null) { return; } Debug.Assert(entryEntityType != null, "If we have a parent navigation property type we should also have an entry type."); // Make sure the entity types are compatible if (!parentNavigationPropertyType.IsAssignableFrom(entryEntityType)) { throw new ODataException(Strings.WriterValidationUtils_EntryTypeInExpandedLinkNotCompatibleWithNavigationPropertyType(entryEntityType.FullTypeName(), parentNavigationPropertyType.FullTypeName())); } }
/// <summary> /// Validates that a navigation property with the specified name exists on a given entity type. /// The entity type can be null if no metadata is available. /// </summary> /// <param name="propertyName">The name of the property to validate.</param> /// <param name="owningEntityType">The owning entity type or null if no metadata is available.</param> /// <returns>The <see cref="IEdmProperty"/> instance representing the navigation property with name <paramref name="propertyName"/> /// or null if no metadata is available.</returns> internal static IEdmNavigationProperty ValidateNavigationPropertyDefined(string propertyName, IEdmEntityType owningEntityType) { Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)"); if (owningEntityType == null) { return(null); } IEdmProperty property = ValidatePropertyDefined(propertyName, owningEntityType); if (property == null) { // We don't support open navigation properties Debug.Assert(owningEntityType.IsOpen, "We should have already failed on non-existing property on a closed type."); throw new ODataException(Strings.ValidationUtils_OpenNavigationProperty(propertyName, owningEntityType.FullTypeName())); } if (property.PropertyKind != EdmPropertyKind.Navigation) { // The property must be a navigation property throw new ODataException(Strings.ValidationUtils_NavigationPropertyExpected(propertyName, owningEntityType.FullTypeName(), property.PropertyKind.ToString())); } return((IEdmNavigationProperty)property); }
/// <summary> /// Validates that a navigation property with the specified name exists on a given entity type. /// The entity type can be null if no metadata is available. /// </summary> /// <param name="propertyName">The name of the property to validate.</param> /// <param name="owningEntityType">The owning entity type or null if no metadata is available.</param> /// <param name="messageReaderSettings">The message reader settings being used.</param> /// <returns>The <see cref="IEdmNavigationProperty"/> instance representing the navigation property with name <paramref name="propertyName"/> /// or null if no metadata is available.</returns> internal static IEdmNavigationProperty ValidateNavigationPropertyDefined( string propertyName, IEdmEntityType owningEntityType, ODataMessageReaderSettings messageReaderSettings) { Debug.Assert(!string.IsNullOrEmpty(propertyName), "!string.IsNullOrEmpty(propertyName)"); Debug.Assert(messageReaderSettings != null, "messageReaderSettings != null"); if (owningEntityType == null) { return null; } IEdmProperty property = ValidateLinkPropertyDefined(propertyName, owningEntityType, messageReaderSettings); if (property == null) { if (owningEntityType.IsOpen && !messageReaderSettings.ReportUndeclaredLinkProperties) { // We don't support open navigation properties throw new ODataException(Strings.ValidationUtils_OpenNavigationProperty(propertyName, owningEntityType.FullTypeName())); } } else if (property.PropertyKind != EdmPropertyKind.Navigation) { // The property must be a navigation property throw new ODataException(Strings.ValidationUtils_NavigationPropertyExpected(propertyName, owningEntityType.FullTypeName(), property.PropertyKind.ToString())); } return (IEdmNavigationProperty)property; }
/// <summary> /// Validates the type of an entry in a top-level feed. /// </summary> /// <param name="entityType">The type of the entry.</param> internal void ValidateEntry(IEdmEntityType entityType) { Debug.Assert(entityType != null, "entityType != null"); // If we don't have a type, store the type of the first item. if (this.itemType == null) { this.itemType = entityType; } // Validate the expected and actual types. if (this.itemType.IsEquivalentTo(entityType)) { return; } // If the types are not equivalent, make sure they have a common base type. IEdmType commonBaseType = EdmLibraryExtensions.GetCommonBaseType(this.itemType, entityType); if (commonBaseType == null) { throw new ODataException(Strings.FeedWithoutExpectedTypeValidator_IncompatibleTypes(entityType.FullTypeName(), this.itemType.FullTypeName())); } this.itemType = (IEdmEntityType)commonBaseType; }
/// <summary> /// Осуществляет получение набора EDM-сущностей, соответствующего заданному типу EDM-сущности. /// </summary> /// <param name="entityType">Тип EDM-сущности, для которого необходимо получить, соответствующий ему набор.</param> /// <returns>Набор EDM-сущностей, соответствующий заданному типу EDM-сущности.</returns> public EdmEntitySet GetEdmEntitySet(IEdmEntityType entityType) { if (entityType == null) { return(null); } return((EdmEntitySet)EntityContainer.EntitySets().FirstOrDefault(el => el.Type.TypeKind == EdmTypeKind.Collection && ((EdmCollectionType)el.Type).ElementType.FullName() == entityType.FullTypeName())); }
/// <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> /// Validates that the specified <paramref name="entry"/> is a valid entry as per the specified type. /// </summary> /// <param name="entry">The entry to validate.</param> /// <param name="entityType">Optional entity type to validate the entry against.</param> /// <param name="model">Model containing the entity type.</param> /// <param name="validateMediaResource">true if the validation of the default MediaResource should be done; false otherwise.</param> /// <remarks>If the <paramref name="entityType"/> is available only entry-level tests are performed, properties and such are not validated.</remarks> internal static void ValidateEntryMetadataResource(ODataEntry entry, IEdmEntityType entityType, IEdmModel model, bool validateMediaResource) { Debug.Assert(entry != null, "entry != null"); if (entityType != null) { Debug.Assert(model != null, "model != null"); Debug.Assert(model.IsUserModel(), "model.IsUserModel()"); if (validateMediaResource) { if (entry.MediaResource == null) { if (entityType.HasStream) { throw new ODataException(Strings.ValidationUtils_EntryWithoutMediaResourceAndMLEType(entityType.FullTypeName())); } } else { if (!entityType.HasStream) { throw new ODataException(Strings.ValidationUtils_EntryWithMediaResourceAndNonMLEType(entityType.FullTypeName())); } } } } }