示例#1
0
        protected internal virtual void PutInternal(CachedDbEntity entityToAdd)
        {
            var type     = entityToAdd.Entity.GetType();
            var cacheKey = CacheKeyMapping.GetEntityCacheKey(type);

            IDictionary <string, CachedDbEntity> map = CachedEntites.ContainsKey(cacheKey) ? CachedEntites[cacheKey] : null;

            if (map == null)
            {
                map = new Dictionary <string, CachedDbEntity>();
                CachedEntites[cacheKey] = map;
            }
            if (entityToAdd.Entity.Id == null)
            {
                entityToAdd.Entity.Id = context.Impl.Context.CommandContext.Scope.Resolve <IDGenerator>().NextId;
            }

            // check whether this object is already present in the cache
            var existingCachedEntity = map.ContainsKey(entityToAdd.Entity.Id) ? map[entityToAdd.Entity.Id] : null;

            if (existingCachedEntity == null)
            {
                map[entityToAdd.Entity.Id] = entityToAdd;
            }
            else
            {
                switch (entityToAdd.EntityState)
                {
                case DbEntityState.Transient:
                    // cannot put TRANSIENT entity if entity with same id already exists in cache.
                    if (existingCachedEntity.EntityState == DbEntityState.Transient)
                    {
                        throw Log.EntityCacheDuplicateEntryException("TRANSIENT", entityToAdd.Entity.Id,
                                                                     entityToAdd.Entity.GetType(), existingCachedEntity.EntityState);
                    }
                    throw Log.AlreadyMarkedEntityInEntityCacheException(entityToAdd.Entity.Id,
                                                                        entityToAdd.Entity.GetType(), existingCachedEntity.EntityState);

                case DbEntityState.Persistent:
                    if (existingCachedEntity.EntityState == DbEntityState.Persistent)
                    {
                        // use new entity state, replacing the existing one.
                        map[entityToAdd.Entity.Id] = entityToAdd;
                        break;
                    }
                    if ((existingCachedEntity.EntityState == DbEntityState.DeletedPersistent) ||
                        (existingCachedEntity.EntityState == DbEntityState.DeletedMerged))
                    {
                        break;
                    }

                    // otherwise fail:
                    throw Log.EntityCacheDuplicateEntryException("PERSISTENT", entityToAdd.Entity.Id,
                                                                 entityToAdd.Entity.GetType(), existingCachedEntity.EntityState);

                case DbEntityState.Merged:
                    if ((existingCachedEntity.EntityState == DbEntityState.Persistent) ||
                        (existingCachedEntity.EntityState == DbEntityState.Merged))
                    {
                        // use new entity state, replacing the existing one.
                        map[entityToAdd.Entity.Id] = entityToAdd;
                        break;
                    }
                    if ((existingCachedEntity.EntityState == DbEntityState.DeletedPersistent) ||
                        (existingCachedEntity.EntityState == DbEntityState.DeletedMerged))
                    {
                        break;
                    }

                    // otherwise fail:
                    throw Log.EntityCacheDuplicateEntryException("MERGED", entityToAdd.Entity.Id,
                                                                 entityToAdd.Entity.GetType(), existingCachedEntity.EntityState);

                default:
                    // deletes are always added
                    map[entityToAdd.Entity.Id] = entityToAdd;
                    break;
                }
            }
        }