Example #1
0
        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;
        }
Example #3
0
        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);
        }
Example #5
0
 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;
 }
Example #6
0
 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;
 }
Example #7
0
 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);
 }
Example #8
0
        /// <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;
        }