예제 #1
0
        /// <summary>
        ///     Merges the specified values into the specified key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <exception cref="System.ArgumentNullException">key</exception>
        public void Merge(EntityRelationshipCacheKey key, IDictionary <long, ISet <long> > value)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }

            /////
            // Ensure the dictionary is a concurrent dictionary.
            /////
            var concurrentDictionary = value as ConcurrentDictionary <long, ISet <long> > ?? new ConcurrentDictionary <long, ISet <long> >(value);

            if (key.Direction == Direction.Forward)
            {
                if (_forwardCache.SetValue(key.EntityId, concurrentDictionary))
                {
                    _reverseCache.Validate(key.EntityId, concurrentDictionary);
                }
            }
            else
            {
                if (_reverseCache.SetValue(key.EntityId, concurrentDictionary))
                {
                    _forwardCache.Validate(key.EntityId, concurrentDictionary);
                }
            }
        }
예제 #2
0
        /// <summary>
        ///     Providers the remove.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">key</exception>
        private bool ProviderRemove(EntityRelationshipCacheKey key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }

            bool result;

            lock ( _syncRoot )
            {
                if (key.Direction == Direction.Forward)
                {
                    IDictionary <long, ISet <long> > typedCachedValues;

                    result = _forwardCache.Remove(key.EntityId, out typedCachedValues);

                    _reverseCache.Remove(key.EntityId, out typedCachedValues);
                }
                else
                {
                    IDictionary <long, ISet <long> > typedCachedValues;

                    result = _reverseCache.Remove(key.EntityId, out typedCachedValues);

                    _forwardCache.Remove(key.EntityId, out typedCachedValues);
                }
            }

            return(result);
        }
예제 #3
0
        /// <summary>
        ///     Fill the EntityRelationshipCache with preloaded data.
        /// </summary>
        /// <param name="entityData"></param>
        private static void AddRelationshipsToCache(EntityData entityData)
        {
            long entityId = entityData.Id.Id;

            // Relationships
            IEnumerable <IGrouping <bool, RelationshipData> > relsByEntityAndDir = entityData.Relationships
                                                                                   .GroupBy(rel => rel.IsReverseActual);

            foreach (var entry in relsByEntityAndDir)
            {
                Direction direction = entry.Key ? Direction.Reverse : Direction.Forward;

                var entityAndDirKey = new EntityRelationshipCacheKey(entityId, direction);

                // Get relationship cache for entity
                IDictionary <long, ISet <long> > cachedRelationships = new ConcurrentDictionary <long, ISet <long> >( );

                // Group by relationship type
                foreach (RelationshipData relTypeEntry in entry)
                {
                    long relTypeId = relTypeEntry.RelationshipTypeId.Id;
                    List <RelationshipInstanceData> values = relTypeEntry.Instances;
                    var relSet = new HashSet <long>(values.Select(value => value.Entity.Id.Id));
                    cachedRelationships[relTypeId] = relSet;
                }

                EntityRelationshipCache.Instance.Merge(entityAndDirKey, cachedRelationships);
            }
        }
예제 #4
0
        /// <summary>
        ///     Tries the parse.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="cacheKey">The cache key.</param>
        /// <returns></returns>
        public static bool TryParse(string key, out EntityRelationshipCacheKey cacheKey)
        {
            cacheKey = null;

            if (!string.IsNullOrEmpty(key))
            {
                string[] args = key.Split('_');

                if (args.Length == 2 && !string.IsNullOrEmpty(args[0]) && !string.IsNullOrEmpty(args[1]))
                {
                    long id;

                    if (long.TryParse(args[0], out id))
                    {
                        Direction direction;

                        if (Enum.TryParse(args[1], out direction))
                        {
                            cacheKey = new EntityRelationshipCacheKey(id, direction);
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
예제 #5
0
        /// <summary>
        ///     Determines whether the specified <see cref="System.Object" /> is equal to this instance.
        /// </summary>
        /// <param name="obj">
        ///     The <see cref="System.Object" /> to compare with this instance.
        /// </param>
        /// <returns>
        ///     <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        public bool Equals(EntityRelationshipCacheKey obj)
        {
            if (obj == null)
            {
                return(false);
            }

            return(EntityId == obj.EntityId && Direction == obj.Direction);
        }
예제 #6
0
        /// <summary>
        ///     Determines whether the specified key contains key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">key</exception>
        public bool ContainsKey(EntityRelationshipCacheKey key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }

            if (key.Direction == Direction.Forward)
            {
                return(_forwardCache.ContainsKey(key.EntityId));
            }

            return(_reverseCache.ContainsKey(key.EntityId));
        }
예제 #7
0
        /// <summary>
        ///     Gets or sets the <see cref="IDictionary{TKey,TValue}" /> with the specified key.
        /// </summary>
        /// <value>
        ///     The <see cref="IDictionary{TKey,TValue}" />.
        /// </value>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">key</exception>
        public IReadOnlyDictionary <long, ISet <long> > this[EntityRelationshipCacheKey key]
        {
            get
            {
                if (key == null)
                {
                    throw new ArgumentNullException("key");
                }

                IReadOnlyDictionary <long, ISet <long> > cacheValue;

                if (!TryGetValue(key, out cacheValue))
                {
                    throw new KeyNotFoundException( );
                }

                return(cacheValue);
            }
        }
예제 #8
0
        /// <summary>
        ///     Tries the get value.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">key</exception>
        public bool TryGetValue(EntityRelationshipCacheKey key, out IReadOnlyDictionary <long, ISet <long> > value)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }

            value = null;

            IDictionary <long, ISet <long> > cacheValue;

            bool result = key.Direction == Direction.Forward ? _forwardCache.TryGetValue(key.EntityId, out cacheValue) : _reverseCache.TryGetValue(key.EntityId, out cacheValue);

            if (result)
            {
                value = new ReadOnlyDictionary <long, ISet <long> >(cacheValue);
            }

            return(result);
        }
예제 #9
0
        /// <summary>
        ///     Removes the specified key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">key</exception>
        public bool Remove(EntityRelationshipCacheKey key)
        {
            using (var entityTypeContext = new EntityTypeContext( ))
            {
                IEntity entity = EntityCache.Instance.Get(key.EntityId);

                if (entity != null)
                {
                    entityTypeContext.Merge(key.EntityId, entity.TypeIds);
                }

                bool result = ProviderRemove(key);

                HashSet <long> typeIds = entityTypeContext.Get(key.EntityId);

                var message = new EntityRelationshipCacheMessage( );
                message.RemoveKeys.Add(new SerializableEntityRelationshipCacheKey(SerializableEntityId.Create(key.EntityId, typeIds), key.Direction));

                MessageChannel.Publish(message, PublishOptions.FireAndForget, false, MergeMessages);

                return(result);
            }
        }
예제 #10
0
        /// <summary>
        ///		Caches the relationship table.
        /// </summary>
        /// <param name="getQuery">Function that returns the query to execute.</param>
        /// <param name="direction">The direction.</param>
        private static void CacheRelationshipTable(Func <string> getQuery, Direction direction)
        {
            using (var context = DatabaseContext.GetContext( ))
            {
                using (var command = context.CreateCommand(getQuery( )))
                {
                    context.AddParameter(command, "@tenantId", DbType.Int64, RequestContext.TenantId);

                    var values = new Dictionary <EntityRelationshipCacheKey, IDictionary <long, ISet <long> > >( );

                    using (IDataReader reader = command.ExecuteReader( ))
                    {
                        long currentTypeId = -1;
                        long currentFromId = -1;

                        EntityRelationshipCacheKey key = null;
                        ConcurrentDictionary <long, ISet <long> > dic = null;
                        ISet <long> set = null;

                        while (reader.Read( ))
                        {
                            long typeId = reader.GetInt64(0);
                            long fromId = reader.GetInt64(1);
                            long toId   = reader.GetInt64(2);

                            if (fromId != currentFromId)
                            {
                                if (dic != null)
                                {
                                    values.Add(key, dic);
                                }

                                key           = new EntityRelationshipCacheKey(fromId, direction);
                                dic           = new ConcurrentDictionary <long, ISet <long> >( );
                                currentFromId = fromId;
                                currentTypeId = -1;
                            }

                            if (typeId != currentTypeId)
                            {
                                set = new HashSet <long>( );

                                if (dic != null)
                                {
                                    dic[typeId] = set;
                                }

                                currentTypeId = typeId;
                            }

                            if (set != null)
                            {
                                set.Add(toId);
                            }
                        }

                        if (dic != null)
                        {
                            values.Add(key, dic);
                        }

                        EntityRelationshipCache.Instance.Preload(values);
                    }
                }
            }
        }