private static ODataEntityPropertyMappingCache EnsureEpmCacheInternal(IEdmModel model, IEdmEntityType entityType, int maxMappingCount, out bool cacheModified) { cacheModified = false; if (entityType == null) { return(null); } IEdmEntityType type = entityType.BaseEntityType(); ODataEntityPropertyMappingCache baseCache = null; if (type != null) { baseCache = EnsureEpmCacheInternal(model, type, maxMappingCount, out cacheModified); } ODataEntityPropertyMappingCache epmCache = model.GetEpmCache(entityType); if (model.HasOwnOrInheritedEpm(entityType)) { ODataEntityPropertyMappingCollection entityPropertyMappings = model.GetEntityPropertyMappings(entityType); if (!(((epmCache == null) || cacheModified) || epmCache.IsDirty(entityPropertyMappings))) { return(epmCache); } cacheModified = true; int totalMappingCount = ValidationUtils.ValidateTotalEntityPropertyMappingCount(baseCache, entityPropertyMappings, maxMappingCount); epmCache = new ODataEntityPropertyMappingCache(entityPropertyMappings, model, totalMappingCount); try { epmCache.BuildEpmForType(entityType, entityType); epmCache.EpmSourceTree.Validate(entityType); model.SetAnnotationValue <ODataEntityPropertyMappingCache>(entityType, epmCache); return(epmCache); } catch { model.RemoveEpmCache(entityType); throw; } } if (epmCache != null) { cacheModified = true; model.RemoveEpmCache(entityType); } return(epmCache); }
/// <summary> /// Ensures that an up-to-date EPM cache exists for the specified <paramref name="entityType"/>. /// If no cache exists, a new one will be created based on the public mappings (if any). /// If the public mappings have changed (and the cache is thus dirty), the method re-constructs the cache. /// If all public mappings have been removed, the method also removes the EPM cache. /// </summary> /// <param name="model">IEdmModel instance containing the annotations.</param> /// <param name="entityType">IEdmEntityType instance for which to ensure the EPM cache.</param> /// <param name="maxMappingCount">The maximum allowed number of entity property mappings /// for a given entity type (on the type itself and all its base types).</param> /// <param name="cacheModified">true if the cache was modified; otherwise false.</param> /// <returns>An instance of <see cref="ODataEntityPropertyMappingCache"/>, if there are any EPM mappings for the given entity type, otherwise returns null.</returns> private static ODataEntityPropertyMappingCache EnsureEpmCacheInternal( IEdmModel model, IEdmEntityType entityType, int maxMappingCount, out bool cacheModified) { cacheModified = false; if (entityType == null) { return null; } // Make sure the EPM of the base type is initialized. IEdmEntityType baseEntityType = entityType.BaseEntityType(); ODataEntityPropertyMappingCache baseCache = null; if (baseEntityType != null) { baseCache = EnsureEpmCacheInternal(model, baseEntityType, maxMappingCount, out cacheModified); } ODataEntityPropertyMappingCache epmCache = model.GetEpmCache(entityType); if (model.HasOwnOrInheritedEpm(entityType)) { ODataEntityPropertyMappingCollection mappings = model.GetEntityPropertyMappings(entityType); bool needToBuildCache = epmCache == null || cacheModified || epmCache.IsDirty(mappings); if (needToBuildCache) { cacheModified = true; int totalMappingCount = ValidationUtils.ValidateTotalEntityPropertyMappingCount(baseCache, mappings, maxMappingCount); epmCache = new ODataEntityPropertyMappingCache(mappings, model, totalMappingCount); // Build the EPM tree and validate it try { epmCache.BuildEpmForType(entityType, entityType); epmCache.EpmSourceTree.Validate(entityType); epmCache.EpmTargetTree.Validate(); // We set the annotation here, so if anything fails during // building of the cache the annotation will not even be set so // not leaving the type in an inconsistent state. model.SetAnnotationValue(entityType, epmCache); } catch { // Remove an existing EPM cache if it is dirty to make sure we don't leave // stale caches in case building of the cache fails. // NOTE: we do this in the catch block to ensure that we always make a single // SetAnnotation call to either set or clear the existing annotation // since the SetAnnotation method is thread-safe model.RemoveEpmCache(entityType); throw; } } } else { if (epmCache != null) { // remove an existing EPM cache if the mappings have been removed from the type cacheModified = true; model.RemoveEpmCache(entityType); } } return epmCache; }
internal static void SaveEpmAnnotationsForProperty(this IEdmModel model, IEdmProperty property, ODataEntityPropertyMappingCache epmCache) { bool flag; bool flag2; Func <EntityPropertyMappingAttribute, bool> predicate = null; string propertyName = property.Name; IEnumerable <EntityPropertyMappingAttribute> source = epmCache.MappingsForDeclaredProperties.Where <EntityPropertyMappingAttribute>(delegate(EntityPropertyMappingAttribute m) { if (!m.SourcePath.StartsWith(propertyName, StringComparison.Ordinal)) { return(false); } if (m.SourcePath.Length != propertyName.Length) { return(m.SourcePath[propertyName.Length] == '/'); } return(true); }); if (property.Type.IsODataPrimitiveTypeKind()) { flag = true; flag2 = false; } else { flag2 = true; if (predicate == null) { predicate = m => m.SourcePath == propertyName; } flag = source.Any <EntityPropertyMappingAttribute>(predicate); } model.SaveEpmAnnotations(property, source, flag, flag2); }
/// <summary> /// Saves the EPM annotations on the given <paramref name="property"/>. /// </summary> /// <param name="model">The <see cref="IEdmModel"/> containing the annotations.</param> /// <param name="property">The <see cref="IEdmProperty"/> to save the EPM annotations for.</param> /// <param name="epmCache">The EPM cache for the owning entity type.</param> internal static void SaveEpmAnnotationsForProperty(this IEdmModel model, IEdmProperty property, ODataEntityPropertyMappingCache epmCache) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(model != null, "model != null"); Debug.Assert(property != null, "property != null"); Debug.Assert(epmCache != null, "epmCache != null"); // get the mappings for the current property; this is based on the source path of the mapping string propertyName = property.Name; IEnumerable<EntityPropertyMappingAttribute> propertyMappings = epmCache.MappingsForDeclaredProperties.Where( m => m.SourcePath.StartsWith(propertyName, StringComparison.Ordinal) && (m.SourcePath.Length == propertyName.Length || m.SourcePath[propertyName.Length] == '/')); bool skipSourcePath; bool removePrefix; if (property.Type.IsODataPrimitiveTypeKind()) { // Since only a single mapping from a primitive property can exist, it is fine to not write the source path. Debug.Assert(propertyMappings.Count() <= 1, "At most one entity property mapping can exist from a primitive property."); skipSourcePath = true; removePrefix = false; } else { Debug.Assert( property.Type.IsODataComplexTypeKind() || property.Type.IsNonEntityODataCollectionTypeKind(), "Only primitive, complex or collectionValue properties can have EPM defined on them."); removePrefix = true; skipSourcePath = propertyMappings.Any(m => m.SourcePath == propertyName); Debug.Assert( !skipSourcePath || propertyMappings.Count() == 1, "We must not have multiple mappings for a property if one of them matches the property name exactly (the other ones would not make sense)."); } model.SaveEpmAnnotations(property, propertyMappings, skipSourcePath, removePrefix); }
internal static int ValidateTotalEntityPropertyMappingCount(ODataEntityPropertyMappingCache baseCache, ODataEntityPropertyMappingCollection mappings, int maxMappingCount) { int num = (baseCache == null) ? 0 : baseCache.TotalMappingCount; int num2 = (mappings == null) ? 0 : mappings.Count; int num3 = num + num2; if (num3 > maxMappingCount) { throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_MaxNumberOfEntityPropertyMappingsExceeded(num3, maxMappingCount)); } return num3; }
private static ODataEntityPropertyMappingCache EnsureEpmCacheInternal(IEdmModel model, IEdmEntityType entityType, int maxMappingCount, out bool cacheModified) { cacheModified = false; if (entityType == null) { return null; } IEdmEntityType type = entityType.BaseEntityType(); ODataEntityPropertyMappingCache baseCache = null; if (type != null) { baseCache = EnsureEpmCacheInternal(model, type, maxMappingCount, out cacheModified); } ODataEntityPropertyMappingCache epmCache = model.GetEpmCache(entityType); if (model.HasOwnOrInheritedEpm(entityType)) { ODataEntityPropertyMappingCollection entityPropertyMappings = model.GetEntityPropertyMappings(entityType); if (!(((epmCache == null) || cacheModified) || epmCache.IsDirty(entityPropertyMappings))) { return epmCache; } cacheModified = true; int totalMappingCount = ValidationUtils.ValidateTotalEntityPropertyMappingCount(baseCache, entityPropertyMappings, maxMappingCount); epmCache = new ODataEntityPropertyMappingCache(entityPropertyMappings, model, totalMappingCount); try { epmCache.BuildEpmForType(entityType, entityType); epmCache.EpmSourceTree.Validate(entityType); model.SetAnnotationValue<ODataEntityPropertyMappingCache>(entityType, epmCache); return epmCache; } catch { model.RemoveEpmCache(entityType); throw; } } if (epmCache != null) { cacheModified = true; model.RemoveEpmCache(entityType); } return epmCache; }
internal static void SaveEpmAnnotationsForProperty(this IEdmModel model, IEdmProperty property, ODataEntityPropertyMappingCache epmCache) { bool flag; bool flag2; Func<EntityPropertyMappingAttribute, bool> predicate = null; string propertyName = property.Name; IEnumerable<EntityPropertyMappingAttribute> source = epmCache.MappingsForDeclaredProperties.Where<EntityPropertyMappingAttribute>(delegate (EntityPropertyMappingAttribute m) { if (!m.SourcePath.StartsWith(propertyName, StringComparison.Ordinal)) { return false; } if (m.SourcePath.Length != propertyName.Length) { return m.SourcePath[propertyName.Length] == '/'; } return true; }); if (property.Type.IsODataPrimitiveTypeKind()) { flag = true; flag2 = false; } else { flag2 = true; if (predicate == null) { predicate = m => m.SourcePath == propertyName; } flag = source.Any<EntityPropertyMappingAttribute>(predicate); } model.SaveEpmAnnotations(property, source, flag, flag2); }
/// <summary> /// Validates that the total number of entity property mapping attributes on the base entity type and the current /// entity type does not exceed the specified security limit. /// </summary> /// <param name="baseCache">The EPM cache of the base entity type or null if no base entity type exists.</param> /// <param name="mappings">The EPM collection of the current entity type.</param> /// <param name="maxMappingCount">The maximum number of mappings allowed for an entity type (on the type itself and all its base types).</param> /// <returns>The total number of entity property mappings for the current entity type.</returns> internal static int ValidateTotalEntityPropertyMappingCount(ODataEntityPropertyMappingCache baseCache, ODataEntityPropertyMappingCollection mappings, int maxMappingCount) { DebugUtils.CheckNoExternalCallers(); int countOfMappingsOnBaseTypes = baseCache == null ? 0 : baseCache.TotalMappingCount; int countOfMappingsOnCurrentType = mappings == null ? 0 : mappings.Count; int totalMappingCount = countOfMappingsOnBaseTypes + countOfMappingsOnCurrentType; if (totalMappingCount > maxMappingCount) { throw new ODataException(Strings.ValidationUtils_MaxNumberOfEntityPropertyMappingsExceeded(totalMappingCount, maxMappingCount)); } return totalMappingCount; }