private void Set(IEntityPersister persister, object[] state, string propertyName, object value)
 {
     var index = Array.IndexOf(persister.PropertyNames, propertyName);
     if (index == -1)
         return;
     state[index] = value;
 }
		/// <summary>
		/// Initializes a new instance of <see cref="ScheduledInsertion"/>.
		/// </summary>
		/// <param name="id">The identifier of the object.</param>
		/// <param name="state">An object array that contains the state of the object being inserted.</param>
		/// <param name="instance">The actual object instance.</param>
		/// <param name="version">The version of the object instance.</param>
		/// <param name="persister">The <see cref="IEntityPersister"/> that is responsible for the persisting the object.</param>
		/// <param name="session">The <see cref="ISessionImplementor"/> that the Action is occuring in.</param>
		public ScheduledInsertion(object id, object[] state, object instance, object version, IEntityPersister persister,
		                          ISessionImplementor session)
			: base(session, id, instance, persister)
		{
			this.state = state;
			this.version = version;
		}
 private static IEnumerable<int> GetAdditionalDirtyProperties(IEntityPersister persister)
 {
     // Always update audit fields, even if their values don't change (dynamic-update=true would prevent this, hence this 'hack')
     var auditingInfoPropertyIndex = Array.IndexOf(persister.PropertyNames, "AuditingInfo");
     if (auditingInfoPropertyIndex != -1)
         yield return auditingInfoPropertyIndex;
 }
		/// <summary>
		/// Associates a given entity (either transient or associated with another session) to the given session.
		/// </summary>
		/// <param name="event">The event triggering the re-association </param>
		/// <param name="entity">The entity to be associated </param>
		/// <param name="id">The id of the entity. </param>
		/// <param name="persister">The entity's persister instance. </param>
		/// <returns> An EntityEntry representing the entity within this session. </returns>
		protected EntityEntry Reassociate(AbstractEvent @event, object entity, object id, IEntityPersister persister)
		{
			if (log.IsDebugEnabled)
			{
				log.Debug("Reassociating transient instance: " + MessageHelper.InfoString(persister, id, @event.Session.Factory));
			}

			IEventSource source = @event.Session;
			EntityKey key = source.GenerateEntityKey(id, persister);

			source.PersistenceContext.CheckUniqueness(key, entity);

			//get a snapshot
			object[] values = persister.GetPropertyValues(entity, source.EntityMode);
			TypeHelper.DeepCopy(values, persister.PropertyTypes, persister.PropertyUpdateability, values, source);
			object version = Versioning.GetVersion(values, persister);

			EntityEntry newEntry = source.PersistenceContext.AddEntity(
				entity,
				persister.IsMutable ? Status.Loaded : Status.ReadOnly,
				values,
				key,
				version,
				LockMode.None,
				true,
				persister,
				false,
				true);

			new OnLockVisitor(source, id, entity).Process(entity, persister);

			persister.AfterReassociate(entity, source);

			return newEntry;
		}
		public EntityDeleteAction(object id, object[] state, object version, object instance, IEntityPersister persister, bool isCascadeDeleteEnabled, ISessionImplementor session)
			: base(session, id, instance, persister)
		{
			this.state = state;
			this.version = version;
			this.isCascadeDeleteEnabled = isCascadeDeleteEnabled;
		}
        public void Update(IAuditable auditable, object[] oldState, object[] state, IEntityPersister persister)
        {
            if (auditable == null)
                return;

            this.SetChange(auditable, state);
        }
        protected override void DeleteEntity(IEventSource session, object entity,

            EntityEntry entityEntry, bool isCascadeDeleteEnabled,

            IEntityPersister persister, ISet transientEntities)
        {
            if (entity is IPermanent)
            {

                var e = (IPermanent)entity;

                e.IsDeleted = true;

                CascadeBeforeDelete(session, persister, entity, entityEntry, transientEntities);

                CascadeAfterDelete(session, persister, entity, transientEntities);

            }

            else
            {

                base.DeleteEntity(session, entity, entityEntry, isCascadeDeleteEnabled,

                                  persister, transientEntities);

            }
        }
 public DelWorkUnit(ISessionImplementor sessionImplementor, String entityName, AuditConfiguration verCfg,
     Object id, IEntityPersister entityPersister, Object[] state)
     : base(sessionImplementor, entityName, verCfg, id)
 {
     this.state = state;
     this.propertyNames = entityPersister.PropertyNames;
 }
            protected override object PerformSave(object entity, object id, IEntityPersister persister, bool useIdentityColumn, object anything,
           IEventSource source, bool requiresImmediateIdAccess)
            {
                var entityValue = entity as EntityBase;
                if (entityValue != null)
                {
                    if (entityValue.CreatedBy == null || entityValue.CreatedBy.Equals(string.Empty))
                    {
                        entityValue.CreatedBy = EntityConstant.CreatedBy;
                        entityValue.CreatedOn = DateTime.Now;
                    }
                    else
                    {
                        entityValue.UpdatedBy = EntityConstant.UpdatedBy;
                        entityValue.UpdatedOn = DateTime.Now;
                    }
                }

                foreach (var property in entity.GetType().GetProperties())
                {
                    var propertyValue = property.GetValue(entity, null);
                    if (propertyValue == null)
                    {
                        continue;
                    }
                    if (propertyValue.GetType().IsSubclassOf(typeof(EntityBase)))
                    {
                        var value = propertyValue as EntityBase;
                        value.CreatedBy = EntityConstant.CreatedBy;
                        value.CreatedOn = DateTime.Now;
                    }
                }

                return base.PerformSave(entityValue, id, persister, useIdentityColumn, anything, source, requiresImmediateIdAccess);
            }
		/// <summary>
		/// Initializes a new instance of <see cref="ScheduledEntityAction"/>.
		/// </summary>
		/// <param name="session">The <see cref="ISessionImplementor"/> that the Action is occuring in.</param>
		/// <param name="id">The identifier of the object.</param>
		/// <param name="instance">The actual object instance.</param>
		/// <param name="persister">The <see cref="IEntityPersister"/> that is responsible for the persisting the object.</param>
		protected ScheduledEntityAction(ISessionImplementor session, object id, object instance, IEntityPersister persister)
		{
			this.session = session;
			this.id = id;
			this.persister = persister;
			this.instance = instance;
		}
		/// <summary> Constructs an event containing the pertinent information. </summary>
		/// <param name="source">The session from which the event originated. </param>
		/// <param name="entity">The entity to be invloved in the database operation. </param>
		/// <param name="id">The entity id to be invloved in the database operation. </param>
		/// <param name="persister">The entity's persister. </param>
		protected AbstractPreDatabaseOperationEvent(IEventSource source, object entity, object id, IEntityPersister persister)
			: base(source)
		{
			Entity = entity;
			Id = id;
			Persister = persister;
		}
		public BatchingEntityLoader(IEntityPersister persister, int[] batchSizes, Loader[] loaders)
		{
			this.batchSizes = batchSizes;
			this.loaders = loaders;
			this.persister = persister;
			idType = persister.IdentifierType;
		}
Beispiel #13
0
		public PreDeleteEvent(object entity, object id, object[] deletedState, IEntityPersister persister)
		{
			this.entity = entity;
			this.id = id;
			this.deletedState = deletedState;
			this.persister = persister;
		}
		private static string DetermineNameOfPropertyToUse(IEntityPersister persister, string supplied)
		{
			if (supplied != null)
			{
				return supplied;
			}
			int[] naturalIdPropertyIndices = persister.NaturalIdentifierProperties;
			if (naturalIdPropertyIndices == null)
			{
				throw new IdentifierGenerationException("no natural-id property defined; need to specify [key] in "
				                                        + "generator parameters");
			}
			if (naturalIdPropertyIndices.Length > 1)
			{
				throw new IdentifierGenerationException("select generator does not currently support composite "
				                                        + "natural-id properties; need to specify [key] in generator parameters");
			}
			ValueInclusion inclusion = persister.PropertyInsertGenerationInclusions[naturalIdPropertyIndices[0]];
			if (inclusion != ValueInclusion.None)
			{
				throw new IdentifierGenerationException("natural-id also defined as insert-generated; need to specify [key] "
				                                        + "in generator parameters");
			}
			return persister.PropertyNames[naturalIdPropertyIndices[0]];
		}
		/// <summary>
		/// Generate small message that can be used in traces and exception messages.
		/// </summary>
		/// <param name="persister">The <see cref="IEntityPersister" /> for the class in question.</param>
		/// <param name="id">The identifier of the object.</param>
		/// <param name="factory">The <see cref="ISessionFactory" />.</param>
		/// <returns>A descriptive <see cref="String" /> in the format of <c>[classname#id]</c></returns>
		public static string InfoString(IEntityPersister persister, object id, ISessionFactoryImplementor factory)
		{
			StringBuilder s = new StringBuilder();
			s.Append('[');
			if (persister == null)
			{
				s.Append("<null Class>");
			}
			else
			{
				s.Append(persister.EntityName);
			}
			s.Append('#');

			if (id == null)
			{
				s.Append("<null>");
			}
			else
			{
				s.Append(id);
			}
			s.Append(']');

			return s.ToString();
		}
		protected virtual void Validate(object entity, IEntityPersister persister, IEventSource source)
		{
			if (persister.ImplementsValidatable(source.EntityMode))
			{
				((IValidatable)entity).Validate();
			}
		}
		public EntityIdentityInsertAction(object[] state, object instance, IEntityPersister persister, ISessionImplementor session, bool isDelayed)
			: base(session, null, instance, persister)
		{
			this.state = state;
			this.isDelayed = isDelayed;
			delayedEntityKey = this.isDelayed ? GenerateDelayedEntityKey() : null;
		}
Beispiel #18
0
     public void Update(IStampedEntity entity, object[] oldState, 
 object[] state, IEntityPersister persister)
     {
         if (entity == null)
           return;
         SetChange(entity, state, persister);
     }
Beispiel #19
0
 public AddWorkUnit(ISessionImplementor sessionImplementor, String entityName, AuditConfiguration verCfg,
     Object id, IEntityPersister entityPersister, Object[] state)
     : base(sessionImplementor, entityName, verCfg, id)
 {
     data = new Dictionary<String, Object>();
     verCfg.EntCfg[EntityName].PropertyMapper.Map(sessionImplementor, data,
         entityPersister.PropertyNames, state, null);
 }
Beispiel #20
0
     private void SetCreate(IStampedEntity entity, object[] state,
 IEntityPersister persister)
     {
         entity.CreatedBy = GetUserName();
         SetState(persister, state, CREATED_BY, entity.CreatedBy);
         entity.CreatedTS = DateTime.Now;
         SetState(persister, state, CREATED_TS, entity.CreatedTS);
     }
Beispiel #21
0
     public void Insert(IStampedEntity entity, object[] state, 
 IEntityPersister persister)
     {
         if (entity == null)
           return;
         SetCreate(entity, state, persister);
         SetChange(entity, state, persister);
     }
Beispiel #22
0
        public DelWorkUnit(ISessionImplementor sessionImplementor, string entityName, AuditConfiguration verCfg,
						   object id, IEntityPersister entityPersister, object[] state)
            : base(sessionImplementor, entityName, verCfg, id, RevisionType.Deleted)
        {
            this.state = state;
            propertyNames = entityPersister.PropertyNames;
            this.entityPersister = entityPersister;
        }
        private void CommitAuditInfo(IEntityPersister persister, object[] state, string propertyName)
        {
            var index = Array.IndexOf(persister.PropertyNames, propertyName);

            if (index == -1) return;

            state[index] = DateTime.UtcNow;
        }
        public void Insert(IAuditable auditable, object[] state, IEntityPersister persister)
        {
            if (auditable == null)
                return;

            this.SetCreate(auditable, state);
            this.SetChange(auditable, state);
        }
Beispiel #25
0
		public PostDeleteEvent(object entity, object id, object[] deletedState, IEntityPersister persister, IEventSource source)
			: base(source)
		{
			this.entity = entity;
			this.id = id;
			this.persister = persister;
			this.deletedState = deletedState;
		}
Beispiel #26
0
		public PreInsertEvent(object entity, object id, object[] state, IEntityPersister persister, ISessionImplementor source)
		{
			this.entity = entity;
			this.id = id;
			this.state = state;
			this.persister = persister;
			this.source = source;
		}
Beispiel #27
0
		public CacheEntry(object[] state, IEntityPersister persister, bool unfetched, object version, ISessionImplementor session, object owner)
		{
			//disassembled state gets put in a new array (we write to cache by value!)
			disassembledState = TypeFactory.Disassemble(state, persister.PropertyTypes, null, session, owner);
			subclass = persister.EntityName;
			lazyPropertiesAreUnfetched = unfetched || !persister.IsLazyPropertiesCacheable;
			this.version = version;
		}
 private void SetState(IEntityPersister persister,
 object[] state, string propertyName, object value)
 {
     var index = GetIndex(persister, propertyName);
     if (index == -1)
         return;
     state[index] = value;
 }
Beispiel #29
0
 public ModWorkUnit(ISessionImplementor sessionImplementor, String entityName, AuditConfiguration verCfg, 
     Object id, IEntityPersister entityPersister, Object[] newState, Object[] oldState)
     : base(sessionImplementor, entityName, verCfg, id)
 {
     data = new Dictionary<String, Object>();
     changes = verCfg.EntCfg[EntityName].PropertyMapper.Map(sessionImplementor, data,
             entityPersister.PropertyNames, newState, oldState);
 }
Beispiel #30
0
		public PostInsertEvent(object entity, object id, object[] state, IEntityPersister persister, IEventSource source)
			: base(source)
		{
			this.entity = entity;
			this.id = id;
			this.state = state;
			this.persister = persister;
		}
Beispiel #31
0
        protected virtual void PerformUpdate(SaveOrUpdateEvent @event, object entity, IEntityPersister persister)
        {
            if (!persister.IsMutable)
            {
                log.Debug("immutable instance passed to doUpdate(), locking");
                Reassociate(@event, entity, @event.RequestedId, persister);
            }
            else
            {
                if (log.IsDebugEnabled)
                {
                    log.Debug("updating " + MessageHelper.InfoString(persister, @event.RequestedId, @event.Session.Factory));
                }

                IEventSource source = @event.Session;

                EntityKey key = new EntityKey(@event.RequestedId, persister, source.EntityMode);

                source.PersistenceContext.CheckUniqueness(key, entity);

                if (InvokeUpdateLifecycle(entity, persister, source))
                {
                    Reassociate(@event, @event.Entity, @event.RequestedId, persister);
                    return;
                }

                // this is a transient object with existing persistent state not loaded by the session
                new OnUpdateVisitor(source, @event.RequestedId, entity).Process(entity, persister);

                //TODO: put this stuff back in to read snapshot from
                //      the second-level cache (needs some extra work)

                /*Object[] cachedState = null;
                 *
                 * if ( persister.hasCache() ) {
                 * CacheEntry entry = (CacheEntry) persister.getCache()
                 * .get( event.getRequestedId(), source.getTimestamp() );
                 * cachedState = entry==null ?
                 * null :
                 * entry.getState(); //TODO: half-assemble this stuff
                 * }*/

                source.PersistenceContext.AddEntity(entity, Status.Loaded, null, key,
                                                    persister.GetVersion(entity, source.EntityMode), LockMode.None, true, persister,
                                                    false, true);

                //persister.AfterReassociate(entity, source); TODO H3.2 not ported

                if (log.IsDebugEnabled)
                {
                    log.Debug("updating " + MessageHelper.InfoString(persister, @event.RequestedId, source.Factory));
                }

                CascadeOnUpdate(@event, persister, entity);
            }
        }
        private bool IsVersionIncrementRequired(FlushEntityEvent @event, EntityEntry entry, IEntityPersister persister, int[] dirtyProperties)
        {
            // NH different behavior: because NH-1756 when PostInsertId is used with a generated version
            // the version is read inmediately after save and does not need to be incremented.
            // BTW, in general, a generated version does not need to be incremented by NH.

            bool isVersionIncrementRequired =
                entry.Status != Status.Deleted && !persister.IsVersionPropertyGenerated &&
                (dirtyProperties == null ||
                 Versioning.IsVersionIncrementRequired(dirtyProperties, @event.HasDirtyCollection, persister.PropertyVersionability));

            return(isVersionIncrementRequired);
        }
 private bool IsCollectionDirtyCheckNecessary(IEntityPersister persister, Status status)
 {
     return((status == Status.Loaded || status == Status.ReadOnly) && persister.IsVersioned && persister.HasCollections);
 }
        public SessionFactoryImpl(Configuration cfg, IMapping mapping, Settings settings, EventListeners listeners)
        {
            Init();
            log.Info("building session factory");

            properties          = new Dictionary <string, string>(cfg.Properties);
            interceptor         = cfg.Interceptor;
            this.settings       = settings;
            sqlFunctionRegistry = new SQLFunctionRegistry(settings.Dialect, cfg.SqlFunctions);
            eventListeners      = listeners;
            filters             = new Dictionary <string, FilterDefinition>(cfg.FilterDefinitions);
            if (log.IsDebugEnabled)
            {
                log.Debug("Session factory constructed with filter configurations : " + CollectionPrinter.ToString(filters));
            }

            if (log.IsDebugEnabled)
            {
                log.Debug("instantiating session factory with properties: " + CollectionPrinter.ToString(properties));
            }

            try
            {
                if (settings.IsKeywordsImportEnabled)
                {
                    SchemaMetadataUpdater.Update(this);
                }
                if (settings.IsAutoQuoteEnabled)
                {
                    SchemaMetadataUpdater.QuoteTableAndColumns(cfg);
                }
            }
            catch (NotSupportedException)
            {
                // Ignore if the Dialect does not provide DataBaseSchema
            }

            #region Caches
            settings.CacheProvider.Start(properties);
            #endregion

            #region Generators
            identifierGenerators = new Dictionary <string, IIdentifierGenerator>();
            foreach (PersistentClass model in cfg.ClassMappings)
            {
                if (!model.IsInherited)
                {
                    IIdentifierGenerator generator =
                        model.Identifier.CreateIdentifierGenerator(settings.Dialect, settings.DefaultCatalogName,
                                                                   settings.DefaultSchemaName, (RootClass)model);

                    identifierGenerators[model.EntityName] = generator;
                }
            }
            #endregion

            #region Persisters

            Dictionary <string, ICacheConcurrencyStrategy> caches = new Dictionary <string, ICacheConcurrencyStrategy>();
            entityPersisters        = new Dictionary <string, IEntityPersister>();
            implementorToEntityName = new Dictionary <System.Type, string>();

            Dictionary <string, IClassMetadata> classMeta = new Dictionary <string, IClassMetadata>();

            foreach (PersistentClass model in cfg.ClassMappings)
            {
                model.PrepareTemporaryTables(mapping, settings.Dialect);
                string cacheRegion = model.RootClazz.CacheRegionName;
                ICacheConcurrencyStrategy cache;
                if (!caches.TryGetValue(cacheRegion, out cache))
                {
                    cache =
                        CacheFactory.CreateCache(model.CacheConcurrencyStrategy, cacheRegion, model.IsMutable, settings, properties);
                    if (cache != null)
                    {
                        caches.Add(cacheRegion, cache);
                        if (!allCacheRegions.TryAdd(cache.RegionName, cache.Cache))
                        {
                            throw new HibernateException("An item with the same key has already been added to allCacheRegions.");
                        }
                    }
                }
                IEntityPersister cp = PersisterFactory.CreateClassPersister(model, cache, this, mapping);
                entityPersisters[model.EntityName] = cp;
                classMeta[model.EntityName]        = cp.ClassMetadata;

                if (model.HasPocoRepresentation)
                {
                    implementorToEntityName[model.MappedClass] = model.EntityName;
                }
            }
            classMetadata = new UnmodifiableDictionary <string, IClassMetadata>(classMeta);

            Dictionary <string, ISet <string> > tmpEntityToCollectionRoleMap = new Dictionary <string, ISet <string> >();
            collectionPersisters = new Dictionary <string, ICollectionPersister>();
            foreach (Mapping.Collection model in cfg.CollectionMappings)
            {
                ICacheConcurrencyStrategy cache =
                    CacheFactory.CreateCache(model.CacheConcurrencyStrategy, model.CacheRegionName, model.Owner.IsMutable, settings,
                                             properties);
                if (cache != null)
                {
                    allCacheRegions[cache.RegionName] = cache.Cache;
                }
                ICollectionPersister persister = PersisterFactory.CreateCollectionPersister(model, cache, this);
                collectionPersisters[model.Role] = persister;
                IType indexType = persister.IndexType;
                if (indexType != null && indexType.IsAssociationType && !indexType.IsAnyType)
                {
                    string        entityName = ((IAssociationType)indexType).GetAssociatedEntityName(this);
                    ISet <string> roles;
                    if (!tmpEntityToCollectionRoleMap.TryGetValue(entityName, out roles))
                    {
                        roles = new HashSet <string>();
                        tmpEntityToCollectionRoleMap[entityName] = roles;
                    }
                    roles.Add(persister.Role);
                }
                IType elementType = persister.ElementType;
                if (elementType.IsAssociationType && !elementType.IsAnyType)
                {
                    string        entityName = ((IAssociationType)elementType).GetAssociatedEntityName(this);
                    ISet <string> roles;
                    if (!tmpEntityToCollectionRoleMap.TryGetValue(entityName, out roles))
                    {
                        roles = new HashSet <string>();
                        tmpEntityToCollectionRoleMap[entityName] = roles;
                    }
                    roles.Add(persister.Role);
                }
            }
            Dictionary <string, ICollectionMetadata> tmpcollectionMetadata = new Dictionary <string, ICollectionMetadata>(collectionPersisters.Count);
            foreach (KeyValuePair <string, ICollectionPersister> collectionPersister in collectionPersisters)
            {
                tmpcollectionMetadata.Add(collectionPersister.Key, collectionPersister.Value.CollectionMetadata);
            }
            collectionMetadata = new UnmodifiableDictionary <string, ICollectionMetadata>(tmpcollectionMetadata);
            collectionRolesByEntityParticipant = new UnmodifiableDictionary <string, ISet <string> >(tmpEntityToCollectionRoleMap);
            #endregion

            #region Named Queries
            namedQueries         = new Dictionary <string, NamedQueryDefinition>(cfg.NamedQueries);
            namedSqlQueries      = new Dictionary <string, NamedSQLQueryDefinition>(cfg.NamedSQLQueries);
            sqlResultSetMappings = new Dictionary <string, ResultSetMappingDefinition>(cfg.SqlResultSetMappings);
            #endregion

            imports = new Dictionary <string, string>(cfg.Imports);

            #region after *all* persisters and named queries are registered
            foreach (IEntityPersister persister in entityPersisters.Values)
            {
                persister.PostInstantiate();
            }
            foreach (ICollectionPersister persister in collectionPersisters.Values)
            {
                persister.PostInstantiate();
            }
            #endregion

            #region Serialization info

            name = settings.SessionFactoryName;
            try
            {
                uuid = (string)UuidGenerator.Generate(null, null);
            }
            catch (Exception)
            {
                throw new AssertionFailure("Could not generate UUID");
            }

            SessionFactoryObjectFactory.AddInstance(uuid, name, this, properties);

            #endregion

            log.Debug("Instantiated session factory");

            #region Schema management
            if (settings.IsAutoCreateSchema)
            {
                new SchemaExport(cfg).Create(false, true);
            }

            if (settings.IsAutoUpdateSchema)
            {
                new SchemaUpdate(cfg).Execute(false, true);
            }
            if (settings.IsAutoValidateSchema)
            {
                new SchemaValidator(cfg, settings).Validate();
            }
            if (settings.IsAutoDropSchema)
            {
                schemaExport = new SchemaExport(cfg);
            }
            #endregion

            #region Obtaining TransactionManager
            // not ported yet
            #endregion

            currentSessionContext = BuildCurrentSessionContext();

            if (settings.IsQueryCacheEnabled)
            {
                updateTimestampsCache = new UpdateTimestampsCache(settings, properties);
                queryCache            = settings.QueryCacheFactory.GetQueryCache(null, updateTimestampsCache, settings, properties);
                queryCaches           = new ConcurrentDictionary <string, IQueryCache>();
            }
            else
            {
                updateTimestampsCache = null;
                queryCache            = null;
                queryCaches           = null;
            }

            #region Checking for named queries
            if (settings.IsNamedQueryStartupCheckingEnabled)
            {
                IDictionary <string, HibernateException> errors = CheckNamedQueries();
                if (errors.Count > 0)
                {
                    StringBuilder failingQueries = new StringBuilder("Errors in named queries: ");
                    foreach (KeyValuePair <string, HibernateException> pair in errors)
                    {
                        failingQueries.Append('{').Append(pair.Key).Append('}');
                        log.Error("Error in named query: " + pair.Key, pair.Value);
                    }
                    throw new HibernateException(failingQueries.ToString());
                }
            }
            #endregion

            Statistics.IsStatisticsEnabled = settings.IsStatisticsEnabled;

            // EntityNotFoundDelegate
            IEntityNotFoundDelegate enfd = cfg.EntityNotFoundDelegate;
            if (enfd == null)
            {
                enfd = new DefaultEntityNotFoundDelegate();
            }
            entityNotFoundDelegate = enfd;
        }
Beispiel #35
0
 protected virtual bool InvokeDeleteLifecycle(IEventSource session, object entity, IEntityPersister persister)
 {
     if (persister.ImplementsLifecycle(session.EntityMode))
     {
         log.Debug("calling onDelete()");
         if (((ILifecycle)entity).OnDelete(session) == LifecycleVeto.Veto)
         {
             log.Debug("deletion vetoed by onDelete()");
             return(true);
         }
     }
     return(false);
 }
        /// <summary> Perform a dirty check, and attach the results to the event</summary>
        protected virtual async Task DirtyCheckAsync(FlushEntityEvent @event, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            object entity = @event.Entity;

            object[]            values    = @event.PropertyValues;
            ISessionImplementor session   = @event.Session;
            EntityEntry         entry     = @event.EntityEntry;
            IEntityPersister    persister = entry.Persister;
            object id = entry.Id;

            object[] loadedState = entry.LoadedState;

            int[] dirtyProperties = session.Interceptor.FindDirty(entity, id, values, loadedState, persister.PropertyNames, persister.PropertyTypes);

            @event.DatabaseSnapshot = null;

            bool interceptorHandledDirtyCheck;
            bool cannotDirtyCheck;

            if (dirtyProperties == null)
            {
                // Interceptor returned null, so do the dirtycheck ourself, if possible
                interceptorHandledDirtyCheck = false;

                cannotDirtyCheck = loadedState == null;                 // object loaded by update()
                if (!cannotDirtyCheck)
                {
                    // dirty check against the usual snapshot of the entity
                    dirtyProperties = await(persister.FindDirtyAsync(values, loadedState, entity, session, cancellationToken)).ConfigureAwait(false);
                }
                else if (entry.Status == Status.Deleted && [email protected]())
                {
                    // A non-modifiable (e.g., read-only or immutable) entity needs to be have
                    // references to transient entities set to null before being deleted. No other
                    // fields should be updated.
                    if (values != entry.DeletedState)
                    {
                        throw new InvalidOperationException("Entity has status Status.Deleted but values != entry.DeletedState");
                    }
                    // Even if loadedState == null, we can dirty-check by comparing currentState and
                    // entry.getDeletedState() because the only fields to be updated are those that
                    // refer to transient entities that are being set to null.
                    // - currentState contains the entity's current property values.
                    // - entry.getDeletedState() contains the entity's current property values with
                    //   references to transient entities set to null.
                    // - dirtyProperties will only contain properties that refer to transient entities
                    object[] currentState = persister.GetPropertyValues(@event.Entity);
                    dirtyProperties  = await(persister.FindDirtyAsync(entry.DeletedState, currentState, entity, session, cancellationToken)).ConfigureAwait(false);
                    cannotDirtyCheck = false;
                }
                else
                {
                    // dirty check against the database snapshot, if possible/necessary
                    object[] databaseSnapshot = await(GetDatabaseSnapshotAsync(session, persister, id, cancellationToken)).ConfigureAwait(false);
                    if (databaseSnapshot != null)
                    {
                        dirtyProperties         = await(persister.FindModifiedAsync(databaseSnapshot, values, entity, session, cancellationToken)).ConfigureAwait(false);
                        cannotDirtyCheck        = false;
                        @event.DatabaseSnapshot = databaseSnapshot;
                    }
                }
            }
            else
            {
                // the Interceptor handled the dirty checking
                cannotDirtyCheck             = false;
                interceptorHandledDirtyCheck = true;
            }

            @event.DirtyProperties = dirtyProperties;
            @event.DirtyCheckHandledByInterceptor = interceptorHandledDirtyCheck;
            @event.DirtyCheckPossible             = !cannotDirtyCheck;
        }
        private async Task <bool> ScheduleUpdateAsync(FlushEntityEvent @event, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            EntityEntry      entry     = @event.EntityEntry;
            IEventSource     session   = @event.Session;
            object           entity    = @event.Entity;
            Status           status    = entry.Status;
            IEntityPersister persister = entry.Persister;

            object[] values = @event.PropertyValues;

            if (log.IsDebugEnabled())
            {
                if (status == Status.Deleted)
                {
                    if (!persister.IsMutable)
                    {
                        log.Debug("Updating immutable, deleted entity: {0}", MessageHelper.InfoString(persister, entry.Id, session.Factory));
                    }
                    else if (!entry.IsModifiableEntity())
                    {
                        log.Debug("Updating non-modifiable, deleted entity: {0}", MessageHelper.InfoString(persister, entry.Id, session.Factory));
                    }
                    else
                    {
                        log.Debug("Updating deleted entity: {0}", MessageHelper.InfoString(persister, entry.Id, session.Factory));
                    }
                }
                else
                {
                    log.Debug("Updating entity: {0}", MessageHelper.InfoString(persister, entry.Id, session.Factory));
                }
            }

            bool intercepted;

            if (!entry.IsBeingReplicated)
            {
                // give the Interceptor a chance to process property values, if the properties
                // were modified by the Interceptor, we need to set them back to the object
                intercepted = await(HandleInterceptionAsync(@event, cancellationToken)).ConfigureAwait(false);
            }
            else
            {
                intercepted = false;
            }

            Validate(entity, persister, status);

            // increment the version number (if necessary)
            object nextVersion = await(GetNextVersionAsync(@event, cancellationToken)).ConfigureAwait(false);

            // if it was dirtied by a collection only
            int[] dirtyProperties = @event.DirtyProperties;
            if (@event.DirtyCheckPossible && dirtyProperties == null)
            {
                if (!intercepted && [email protected])
                {
                    throw new AssertionFailure("dirty, but no dirty properties");
                }
                dirtyProperties = Array.Empty <int>();
            }

            // check nullability but do not perform command execute
            // we'll use scheduled updates for that.
            new Nullability(session).CheckNullability(values, persister, true);

            // schedule the update
            // note that we intentionally do _not_ pass in currentPersistentState!
            session.ActionQueue.AddAction(
                new EntityUpdateAction(
                    entry.Id,
                    values,
                    dirtyProperties,
                    @event.HasDirtyCollection,
                    status == Status.Deleted && !entry.IsModifiableEntity() ? persister.GetPropertyValues(entity) : entry.LoadedState,
                    entry.Version,
                    nextVersion,
                    entity,
                    persister,
                    session));

            return(intercepted);
        }
 /// <summary>
 /// Add an uninitialized instance of an entity class, as a placeholder to ensure object
 /// identity. Must be called before <tt>postHydrate()</tt>.
 /// Create a "temporary" entry for a newly instantiated entity. The entity is uninitialized,
 /// but we need the mapping from id to instance in order to guarantee uniqueness.
 /// </summary>
 public static void AddUninitializedEntity(EntityKey key, object obj, IEntityPersister persister, LockMode lockMode, ISessionImplementor session)
 {
     session.PersistenceContext.AddEntity(obj, Status.Loading, null, key, null, lockMode, true, persister, false);
 }
Beispiel #39
0
 /// <summary>
 /// We encountered a delete request on a transient instance.
 /// <p/>
 /// This is a deviation from historical Hibernate (pre-3.2) behavior to
 /// align with the JPA spec, which states that transient entities can be
 /// passed to remove operation in which case cascades still need to be
 /// performed.
 ///  </summary>
 /// <param name="session">The session which is the source of the event </param>
 /// <param name="entity">The entity being delete processed </param>
 /// <param name="cascadeDeleteEnabled">Is cascading of deletes enabled</param>
 /// <param name="persister">The entity persister </param>
 /// <param name="transientEntities">
 /// A cache of already visited transient entities (to avoid infinite recursion).
 /// </param>
 /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param>
 protected virtual async Task DeleteTransientEntityAsync(IEventSource session, object entity, bool cascadeDeleteEnabled, IEntityPersister persister, ISet <object> transientEntities, CancellationToken cancellationToken)
 {
     cancellationToken.ThrowIfCancellationRequested();
     log.Info("handling transient entity in delete processing");
     // NH different impl : NH-1895
     if (transientEntities == null)
     {
         transientEntities = new HashSet <object>();
     }
     if (!transientEntities.Add(entity))
     {
         log.Debug("already handled transient entity; skipping");
         return;
     }
     await(CascadeBeforeDeleteAsync(session, persister, entity, null, transientEntities, cancellationToken)).ConfigureAwait(false);
     await(CascadeAfterDeleteAsync(session, persister, entity, transientEntities, cancellationToken)).ConfigureAwait(false);
 }
Beispiel #40
0
        /// <summary>
        /// Perform the entity deletion.  Well, as with most operations, does not
        /// really perform it; just schedules an action/execution with the
        /// <see cref="ActionQueue"/> for execution during flush.
        /// </summary>
        /// <param name="session">The originating session </param>
        /// <param name="entity">The entity to delete </param>
        /// <param name="entityEntry">The entity's entry in the <see cref="ISession"/> </param>
        /// <param name="isCascadeDeleteEnabled">Is delete cascading enabled? </param>
        /// <param name="persister">The entity persister. </param>
        /// <param name="transientEntities">A cache of already deleted entities. </param>
        /// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param>
        protected virtual async Task DeleteEntityAsync(IEventSource session, object entity, EntityEntry entityEntry, bool isCascadeDeleteEnabled, IEntityPersister persister, ISet <object> transientEntities, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            if (log.IsDebugEnabled)
            {
                log.Debug("deleting " + MessageHelper.InfoString(persister, entityEntry.Id, session.Factory));
            }

            IPersistenceContext persistenceContext = session.PersistenceContext;

            IType[] propTypes = persister.PropertyTypes;
            object  version   = entityEntry.Version;

            object[] currentState;
            if (entityEntry.LoadedState == null)
            {
                //ie. the entity came in from update()
                currentState = persister.GetPropertyValues(entity);
            }
            else
            {
                currentState = entityEntry.LoadedState;
            }

            object[] deletedState = CreateDeletedState(persister, currentState, session);
            entityEntry.DeletedState = deletedState;

            session.Interceptor.OnDelete(entity, entityEntry.Id, deletedState, persister.PropertyNames, propTypes);

            // before any callbacks, etc, so subdeletions see that this deletion happened first
            persistenceContext.SetEntryStatus(entityEntry, Status.Deleted);
            EntityKey key = session.GenerateEntityKey(entityEntry.Id, persister);

            await(CascadeBeforeDeleteAsync(session, persister, entity, entityEntry, transientEntities, cancellationToken)).ConfigureAwait(false);

            await(new ForeignKeys.Nullifier(entity, true, false, session).NullifyTransientReferencesAsync(entityEntry.DeletedState, propTypes, cancellationToken)).ConfigureAwait(false);
            new Nullability(session).CheckNullability(entityEntry.DeletedState, persister, true);
            persistenceContext.NullifiableEntityKeys.Add(key);

            // Ensures that containing deletions happen before sub-deletions
            session.ActionQueue.AddAction(new EntityDeleteAction(entityEntry.Id, deletedState, version, entity, persister, isCascadeDeleteEnabled, session));

            await(CascadeAfterDeleteAsync(session, persister, entity, transientEntities, cancellationToken)).ConfigureAwait(false);

            // the entry will be removed after the flush, and will no longer
            // override the stale snapshot
            // This is now handled by removeEntity() in EntityDeleteAction
            //persistenceContext.removeDatabaseSnapshot(key);
        }
        public void SetUp()
        {
            sessionFactory = SessionFactoryHelper.Build();

            persisterForTestSaga = sessionFactory.GetEntityPersisterFor <TestSaga>();
        }
 public EntityKey GenerateEntityKey(object id, IEntityPersister persister)
 {
     return(new EntityKey(id, persister));
 }
Beispiel #43
0
 /// <summary> Cascade an action from the parent entity instance to all its children. </summary>
 /// <param name="persister">The parent's entity persister </param>
 /// <param name="parent">The parent reference. </param>
 public void CascadeOn(IEntityPersister persister, object parent)
 {
     CascadeOn(persister, parent, null);
 }
 private async Task <object[]> GetDatabaseSnapshotAsync(ISessionImplementor session, IEntityPersister persister, object id, CancellationToken cancellationToken)
 {
     cancellationToken.ThrowIfCancellationRequested();
     if (persister.IsSelectBeforeUpdateRequired)
     {
         object[] snapshot = await(session.PersistenceContext.GetDatabaseSnapshotAsync(id, persister, cancellationToken)).ConfigureAwait(false);
         if (snapshot == null)
         {
             //do we even really need this? the update will fail anyway....
             if (session.Factory.Statistics.IsStatisticsEnabled)
             {
                 session.Factory.StatisticsImplementor.OptimisticFailure(persister.EntityName);
             }
             throw new StaleObjectStateException(persister.EntityName, id);
         }
         else
         {
             return(snapshot);
         }
     }
     else
     {
         //TODO: optimize away this lookup for entities w/o unsaved-value="undefined"
         EntityKey entityKey = session.GenerateEntityKey(id, persister);
         return(session.PersistenceContext.GetCachedDatabaseSnapshot(entityKey));
     }
 }
Beispiel #45
0
 /// <summary>
 /// We encountered a delete request on a transient instance.
 /// <p/>
 /// This is a deviation from historical Hibernate (pre-3.2) behavior to
 /// align with the JPA spec, which states that transient entities can be
 /// passed to remove operation in which case cascades still need to be
 /// performed.
 ///  </summary>
 /// <param name="session">The session which is the source of the event </param>
 /// <param name="entity">The entity being delete processed </param>
 /// <param name="cascadeDeleteEnabled">Is cascading of deletes enabled</param>
 /// <param name="persister">The entity persister </param>
 /// <param name="transientEntities">
 /// A cache of already visited transient entities (to avoid infinite recursion).
 /// </param>
 protected virtual void DeleteTransientEntity(IEventSource session, object entity, bool cascadeDeleteEnabled, IEntityPersister persister, ISet transientEntities)
 {
     log.Info("handling transient entity in delete processing");
     // NH different impl : NH-1895
     if (transientEntities == null)
     {
         transientEntities = new HashedSet();
     }
     if (!transientEntities.Add(entity))
     {
         log.Debug("already handled transient entity; skipping");
         return;
     }
     CascadeBeforeDelete(session, persister, entity, null, transientEntities);
     CascadeAfterDelete(session, persister, entity, transientEntities);
 }
Beispiel #46
0
        public override void Execute()
        {
            IEntityPersister    persister = Persister;
            ISessionImplementor session   = Session;
            object instance = Instance;
            object id       = Id;

            bool      statsEnabled = Session.Factory.Statistics.IsStatisticsEnabled;
            Stopwatch stopwatch    = null;

            if (statsEnabled)
            {
                stopwatch = Stopwatch.StartNew();
            }

            bool veto = PreInsert();

            // Don't need to lock the cache here, since if someone
            // else inserted the same pk first, the insert would fail
            if (!veto)
            {
                persister.Insert(id, state, instance, Session);

                EntityEntry entry = Session.PersistenceContext.GetEntry(instance);
                if (entry == null)
                {
                    throw new AssertionFailure("Possible nonthreadsafe access to session");
                }

                entry.PostInsert();

                if (persister.HasInsertGeneratedProperties)
                {
                    persister.ProcessInsertGeneratedProperties(id, instance, state, Session);
                    if (persister.IsVersionPropertyGenerated)
                    {
                        version = Versioning.GetVersion(state, persister);
                    }
                    entry.PostUpdate(instance, state, version);
                }
            }

            ISessionFactoryImplementor factory = Session.Factory;

            if (IsCachePutEnabled(persister))
            {
                CacheEntry ce = new CacheEntry(state, persister, persister.HasUninitializedLazyProperties(instance), version, session, instance);
                cacheEntry = persister.CacheEntryStructure.Structure(ce);

                CacheKey ck  = Session.GenerateCacheKey(id, persister.IdentifierType, persister.RootEntityName);
                bool     put = persister.Cache.Insert(ck, cacheEntry, version);

                if (put && factory.Statistics.IsStatisticsEnabled)
                {
                    factory.StatisticsImplementor.SecondLevelCachePut(Persister.Cache.RegionName);
                }
            }

            PostInsert();

            if (statsEnabled && !veto)
            {
                stopwatch.Stop();
                factory.StatisticsImplementor.InsertEntity(Persister.EntityName, stopwatch.Elapsed);
            }
        }
        protected virtual void EntityIsDetached(MergeEvent @event, IDictionary copyCache)
        {
            log.Debug("merging detached instance");

            object       entity = @event.Entity;
            IEventSource source = @event.Session;

            IEntityPersister persister  = source.GetEntityPersister(@event.EntityName, entity);
            string           entityName = persister.EntityName;

            object id = @event.RequestedId;

            if (id == null)
            {
                id = persister.GetIdentifier(entity, source.EntityMode);
            }
            else
            {
                // check that entity id = requestedId
                object entityId = persister.GetIdentifier(entity, source.EntityMode);
                if (!persister.IdentifierType.IsEqual(id, entityId, source.EntityMode, source.Factory))
                {
                    throw new HibernateException("merge requested with id not matching id of passed entity");
                }
            }

            string previousFetchProfile = source.FetchProfile;

            source.FetchProfile = "merge";

            //we must clone embedded composite identifiers, or
            //we will get back the same instance that we pass in
            object clonedIdentifier = persister.IdentifierType.DeepCopy(id, source.EntityMode, source.Factory);
            object result           = source.Get(persister.EntityName, clonedIdentifier);

            source.FetchProfile = previousFetchProfile;

            if (result == null)
            {
                //TODO: we should throw an exception if we really *know* for sure
                //      that this is a detached instance, rather than just assuming
                //throw new StaleObjectStateException(entityName, id);

                // we got here because we assumed that an instance
                // with an assigned id was detached, when it was
                // really persistent
                EntityIsTransient(@event, copyCache);
            }
            else
            {
                // NH different behavior : NH-1517
                if (InvokeUpdateLifecycle(entity, persister, source))
                {
                    return;
                }

                copyCache[entity] = result;                 //before cascade!

                object target = source.PersistenceContext.Unproxy(result);
                if (target == entity)
                {
                    throw new AssertionFailure("entity was not detached");
                }
                else if (!source.GetEntityName(target).Equals(entityName))
                {
                    throw new WrongClassException("class of the given object did not match class of persistent copy",
                                                  @event.RequestedId, persister.EntityName);
                }
                else if (IsVersionChanged(entity, source, persister, target))
                {
                    if (source.Factory.Statistics.IsStatisticsEnabled)
                    {
                        source.Factory.StatisticsImplementor.OptimisticFailure(entityName);
                    }
                    throw new StaleObjectStateException(persister.EntityName, id);
                }

                // cascade first, so that all unsaved objects get their
                // copy created before we actually copy
                CascadeOnMerge(source, persister, entity, copyCache);
                CopyValues(persister, entity, target, source, copyCache);

                //copyValues works by reflection, so explicitly mark the entity instance dirty
                MarkInterceptorDirty(entity, target);

                @event.Result = result;
            }
        }
Beispiel #48
0
 private int GetIndex(IEntityPersister persister,
                      string propertyName)
 {
     return(Array.IndexOf(persister.PropertyNames,
                          propertyName));
 }
Beispiel #49
0
 /// <summary>
 /// Get the version number of the given instance state snapshot
 /// </summary>
 /// <param name="fields">An array of objects that contains a snapshot of a persistent object.</param>
 /// <param name="persister">The <see cref="IEntityPersister"/> that is responsible for persisting the values of the <c>fields</c> parameter.</param>
 /// <returns>
 /// The value of the version contained in the <c>fields</c> parameter or null if the
 /// Entity is not versioned.
 /// </returns>
 public static object GetVersion(object[] fields, IEntityPersister persister)
 {
     return(persister.IsVersioned ? fields[persister.VersionProperty] : null);
 }
 /// <summary> Cascade behavior is redefined by this subclass, disable superclass behavior</summary>
 protected override void CascadeBeforeSave(IEventSource source, IEntityPersister persister, object entity, object anything)
 {
 }
Beispiel #51
0
 public EntityInsertAction(object id, object[] state, object instance, object version, IEntityPersister persister, ISessionImplementor session)
     : base(session, id, instance, persister)
 {
     this.state   = state;
     this.version = version;
 }
        public virtual void OnMerge(MergeEvent @event, IDictionary copyCache)
        {
            IEventSource source   = @event.Session;
            object       original = @event.Original;

            if (original != null)
            {
                object entity;
                if (original is INHibernateProxy)
                {
                    ILazyInitializer li = ((INHibernateProxy)original).HibernateLazyInitializer;
                    if (li.IsUninitialized)
                    {
                        log.Debug("ignoring uninitialized proxy");
                        @event.Result = source.Load(li.PersistentClass, li.Identifier);
                        return;                         //EARLY EXIT!
                    }
                    else
                    {
                        entity = li.GetImplementation();
                    }
                }
                else
                {
                    entity = original;
                }

                if (copyCache.Contains(entity))
                {
                    log.Debug("already merged");
                    @event.Result = entity;
                }
                else
                {
                    @event.Entity = entity;
                    EntityState entityState = EntityState.Undefined;

                    // Check the persistence context for an entry relating to this
                    // entity to be merged...
                    EntityEntry entry = source.PersistenceContext.GetEntry(entity);
                    if (entry == null)
                    {
                        IEntityPersister persister = source.GetEntityPersister(@event.EntityName, entity);
                        object           id        = persister.GetIdentifier(entity, source.EntityMode);
                        if (id != null)
                        {
                            EntityKey key           = new EntityKey(id, persister, source.EntityMode);
                            object    managedEntity = source.PersistenceContext.GetEntity(key);
                            entry = source.PersistenceContext.GetEntry(managedEntity);
                            if (entry != null)
                            {
                                // we have specialized case of a detached entity from the
                                // perspective of the merge operation.  Specifically, we
                                // have an incoming entity instance which has a corresponding
                                // entry in the current persistence context, but registered
                                // under a different entity instance
                                entityState = EntityState.Detached;
                            }
                        }
                    }

                    if (entityState == EntityState.Undefined)
                    {
                        entityState = GetEntityState(entity, @event.EntityName, entry, source);
                    }

                    switch (entityState)
                    {
                    case EntityState.Persistent:
                        EntityIsPersistent(@event, copyCache);
                        break;

                    case EntityState.Transient:
                        EntityIsTransient(@event, copyCache);
                        break;

                    case EntityState.Detached:
                        EntityIsDetached(@event, copyCache);
                        break;

                    default:
                        throw new ObjectDeletedException("deleted instance passed to merge", null, GetLoggableName(@event.EntityName, entity));
                    }
                }
            }
        }
Beispiel #53
0
 private bool IsCachePutEnabled(IEntityPersister persister)
 {
     return
         (persister.HasCache && !persister.IsCacheInvalidationRequired &&
          ((Session.CacheMode & CacheMode.Put) == CacheMode.Put));
 }
Beispiel #54
0
        private void DereferenceCollection(CollectionType collectionType, bool implicitJoin, bool indexed, string classAlias)
        {
            _dereferenceType = DerefCollection;
            string role = collectionType.Role;

            //foo.bars.size (also handles deprecated stuff like foo.bars.maxelement for backwardness)
            IASTNode sibling        = NextSibling;
            bool     isSizeProperty = sibling != null && CollectionProperties.IsAnyCollectionProperty(sibling.Text);

            if (isSizeProperty)
            {
                indexed = true;                 //yuck!}
            }

            IQueryableCollection queryableCollection = SessionFactoryHelper.RequireQueryableCollection(role);
            string     propName          = Path;
            FromClause currentFromClause = Walker.CurrentFromClause;

            if (Walker.StatementType != HqlSqlWalker.SELECT && indexed && classAlias == null)
            {
                // should indicate that we are processing an INSERT/UPDATE/DELETE
                // query with a subquery implied via a collection property
                // function. Here, we need to use the table name itself as the
                // qualification alias.
                // TODO : verify this works for all databases...
                // TODO : is this also the case in non-"indexed" scenarios?
                string alias = GetLhs().FromElement.Queryable.TableName;
                _columns = FromElement.ToColumns(alias, _propertyPath, false, true);
            }

            //We do not look for an existing join on the same path, because
            //it makes sense to join twice on the same collection role
            var factory = new FromElementFactory(
                currentFromClause,
                GetLhs().FromElement,
                propName,
                classAlias,
                GetColumns(),
                implicitJoin
                );
            FromElement elem = factory.CreateCollection(queryableCollection, role, _joinType, _fetch, indexed);

            if (Log.IsDebugEnabled())
            {
                Log.Debug("dereferenceCollection() : Created new FROM element for {0} : {1}", propName, elem);
            }

            SetImpliedJoin(elem);
            FromElement = elem;                 // This 'dot' expression now refers to the resulting from element.

            if (isSizeProperty)
            {
                elem.Text             = "";
                elem.UseWhereFragment = false;
            }

            if (!implicitJoin)
            {
                IEntityPersister entityPersister = elem.EntityPersister;
                if (entityPersister != null)
                {
                    Walker.AddQuerySpaces(entityPersister.QuerySpaces);
                }
            }
            Walker.AddQuerySpaces(queryableCollection.CollectionSpaces);                // Always add the collection's query spaces.
        }
Beispiel #55
0
        /// <summary>
        /// Associates a given entity (either transient or associated with another session) to the given session.
        /// </summary>
        /// <param name="event">The event triggering the re-association </param>
        /// <param name="entity">The entity to be associated </param>
        /// <param name="id">The id of the entity. </param>
        /// <param name="persister">The entity's persister instance. </param>
        /// <returns> An EntityEntry representing the entity within this session. </returns>
        protected EntityEntry Reassociate(AbstractEvent @event, object entity, object id, IEntityPersister persister)
        {
            if (log.IsDebugEnabled)
            {
                log.Debug("Reassociating transient instance: " +
                          MessageHelper.InfoString(persister, id, @event.Session.Factory));
            }

            IEventSource source = @event.Session;
            EntityKey    key    = new EntityKey(id, persister, source.EntityMode);

            source.PersistenceContext.CheckUniqueness(key, entity);

            //get a snapshot
            object[] values = persister.GetPropertyValues(entity, source.EntityMode);
            TypeFactory.DeepCopy(values, persister.PropertyTypes, persister.PropertyUpdateability, values, source);
            object version = Versioning.GetVersion(values, persister);

            EntityEntry newEntry = source.PersistenceContext.AddEntity(entity, Status.Loaded, values, key, version, LockMode.None, true, persister, false, true);

            new OnLockVisitor(source, id, entity).Process(entity, persister);

            persister.AfterReassociate(entity, source);

            return(newEntry);
        }
Beispiel #56
0
    /// <summary>
    /// Recursive Helper for <see cref="IsReferencedByCompositeId(IEntityPersister)"/>.
    /// </summary>
    /// <param name="rootEM"></param>
    /// <param name="nestedEM"></param>
    /// <param name="neestedIsCompositeId"></param>
    /// <param name="visitedList"></param>
    /// <returns></returns>
    private EntityMetamodel GetReferrerByCompositeId(
        EntityMetamodel rootEM,
        EntityMetamodel nestedEM,
        bool neestedIsCompositeId,
        ICollection <EntityMetamodel> visitedList)
    {
        EntityMetamodel emResult = null;

        if (visitedList.Contains(nestedEM))
        {
            return(emResult);
        }
        else
        {
            visitedList.Add(nestedEM);
            ISessionFactoryImplementor sessionImplementor = rootEM.SessionFactory;
            if (nestedEM.IdentifierProperty.Type is IAbstractComponentType)
            {
                IAbstractComponentType componentType = (IAbstractComponentType)nestedEM.IdentifierProperty.Type;
                for (int i = 0; i < componentType.Subtypes.Length; i++)
                {
                    IType subType = componentType.Subtypes[i];
                    if (!subType.IsAnyType &&
                        subType.IsAssociationType &&
                        subType is IAssociationType)
                    {
                        IAssociationType associationType      = (IAssociationType)subType;
                        string           associatedEntityName = null;
                        try
                        {
                            //for 'Collection Types', sometimes 'Element Type' is not an 'Entity Type'
                            associatedEntityName = associationType.GetAssociatedEntityName(sessionImplementor);
                        }
                        catch (MappingException me)
                        {
                            //I think it will never happen because a
                            //"Composit Id" can not have a property that
                            //uses 'NHibernate.Type.CollectionType'.
                            //But just in case ...
                            if (log.IsDebugEnabled)
                            {
                                log.Debug("Can not perform 'GetAssociatedEntityName'. " +
                                          "Considering it is not an entity type: '" +
                                          nestedEM.IdentifierProperty.Name + "." +
                                          componentType.PropertyNames[i] + "'"
                                          , me);
                            }
                        }
                        if (associatedEntityName != null)
                        {
                            IEntityPersister persisterNextNested = sessionImplementor.GetEntityPersister(associatedEntityName);
                            if (rootEM == persisterNextNested.EntityMetamodel)
                            {
                                emResult = nestedEM;
                                return(emResult);
                            }
                            else
                            {
                                emResult = this.GetReferrerByCompositeId(
                                    rootEM,
                                    persisterNextNested.EntityMetamodel,
                                    true,
                                    visitedList);
                                if (emResult != null)
                                {
                                    return(emResult);
                                }
                            }
                        }
                    }
                }
            }
            for (int i = 0; i < nestedEM.Properties.Length; i++)
            {
                StandardProperty property = nestedEM.Properties[i];
                if (!property.Type.IsAnyType &&
                    property.Type.IsAssociationType &&
                    property.Type is IAssociationType)
                {
                    IAssociationType associationType      = (IAssociationType)property.Type;
                    string           associatedEntityName = null;
                    try
                    {
                        //for 'Collection Types', sometimes 'Element Type' is not an 'Entity Type'
                        associatedEntityName = associationType.GetAssociatedEntityName(sessionImplementor);
                    }
                    catch (MappingException me)
                    {
                        if (log.IsDebugEnabled)
                        {
                            log.Debug("Can not perform 'GetAssociatedEntityName'. " +
                                      "Considering it is not an entity type: '" +
                                      nestedEM.EntityType.Name + "." +
                                      nestedEM.PropertyNames[i] + "'",
                                      me);
                        }
                    }
                    if (associatedEntityName != null)
                    {
                        IEntityPersister persisterNextNested = sessionImplementor.GetEntityPersister(associatedEntityName);
                        emResult = this.GetReferrerByCompositeId(
                            rootEM,
                            persisterNextNested.EntityMetamodel,
                            false,
                            visitedList);
                        if (emResult != null)
                        {
                            return(emResult);
                        }
                    }
                }
            }
        }
        return(null);
    }
 // Evict collections from the factory-level cache
 private void EvictCachedCollections(IEntityPersister persister, object id, ISessionFactoryImplementor factory)
 {
     EvictCachedCollections(persister.PropertyTypes, id, factory);
 }
Beispiel #58
0
 public NamedQueryLoader(string queryName, IEntityPersister persister)
 {
     this.queryName = queryName;
     this.persister = persister;
 }
        /// <summary>
        /// Perform the second step of 2-phase load. Fully initialize the entity instance.
        /// After processing a JDBC result set, we "resolve" all the associations
        /// between the entities which were instantiated and had their state
        /// "hydrated" into an array
        /// </summary>
        internal static void InitializeEntity(object entity, bool readOnly, ISessionImplementor session, PreLoadEvent preLoadEvent, PostLoadEvent postLoadEvent,
                                              Action <IEntityPersister, CachePutData> cacheBatchingHandler)
        {
            //TODO: Should this be an InitializeEntityEventListener??? (watch out for performance!)

            Stopwatch stopWatch = null;

            if (session.Factory.Statistics.IsStatisticsEnabled)
            {
                stopWatch = Stopwatch.StartNew();
            }

            IPersistenceContext persistenceContext = session.PersistenceContext;
            EntityEntry         entityEntry        = persistenceContext.GetEntry(entity);

            if (entityEntry == null)
            {
                throw new AssertionFailure("possible non-threadsafe access to the session");
            }
            IEntityPersister persister = entityEntry.Persister;
            object           id        = entityEntry.Id;

            object[] hydratedState = entityEntry.LoadedState;

            if (log.IsDebugEnabled())
            {
                log.Debug("resolving associations for {0}", MessageHelper.InfoString(persister, id, session.Factory));
            }

            IType[] types = persister.PropertyTypes;
            var     collectionToResolveIndexes = new List <int>(hydratedState.Length);

            for (int i = 0; i < hydratedState.Length; i++)
            {
                object value = hydratedState[i];
                if (!Equals(LazyPropertyInitializer.UnfetchedProperty, value) && !(Equals(BackrefPropertyAccessor.Unknown, value)))
                {
                    if (types[i].IsCollectionType)
                    {
                        // Resolve them last, because they may depend on other properties if they use a property-ref
                        collectionToResolveIndexes.Add(i);
                        continue;
                    }

                    hydratedState[i] = CustomEntityTypeMapper.Map(types[i]).ResolveIdentifier(value, session, entity);
                }
            }

            foreach (var i in collectionToResolveIndexes)
            {
                hydratedState[i] = CustomEntityTypeMapper.Map(types[i]).ResolveIdentifier(hydratedState[i], session, entity);
            }

            //Must occur after resolving identifiers!
            if (session.IsEventSource)
            {
                preLoadEvent.Entity    = entity;
                preLoadEvent.State     = hydratedState;
                preLoadEvent.Id        = id;
                preLoadEvent.Persister = persister;
                IPreLoadEventListener[] listeners = session.Listeners.PreLoadEventListeners;
                for (int i = 0; i < listeners.Length; i++)
                {
                    listeners[i].OnPreLoad(preLoadEvent);
                }
            }

            persister.SetPropertyValues(entity, hydratedState);

            ISessionFactoryImplementor factory = session.Factory;

            if (persister.HasCache && session.CacheMode.HasFlag(CacheMode.Put))
            {
                if (log.IsDebugEnabled())
                {
                    log.Debug("adding entity to second-level cache: {0}", MessageHelper.InfoString(persister, id, session.Factory));
                }

                object     version = Versioning.GetVersion(hydratedState, persister);
                CacheEntry entry   =
                    CacheEntry.Create(hydratedState, persister, version, session, entity);
                CacheKey cacheKey = session.GenerateCacheKey(id, persister.IdentifierType, persister.RootEntityName);

                if (cacheBatchingHandler != null && persister.IsBatchLoadable)
                {
                    cacheBatchingHandler(
                        persister,
                        new CachePutData(
                            cacheKey,
                            persister.CacheEntryStructure.Structure(entry),
                            version,
                            persister.IsVersioned ? persister.VersionType.Comparator : null,
                            UseMinimalPuts(session, entityEntry)));
                }
                else
                {
                    bool put =
                        persister.Cache.Put(cacheKey, persister.CacheEntryStructure.Structure(entry), session.Timestamp, version,
                                            persister.IsVersioned ? persister.VersionType.Comparator : null,
                                            UseMinimalPuts(session, entityEntry));

                    if (put && factory.Statistics.IsStatisticsEnabled)
                    {
                        factory.StatisticsImplementor.SecondLevelCachePut(persister.Cache.RegionName);
                    }
                }
            }

            bool isReallyReadOnly = readOnly;

            if (!persister.IsMutable)
            {
                isReallyReadOnly = true;
            }
            else
            {
                object proxy = persistenceContext.GetProxy(entityEntry.EntityKey);
                if (proxy != null)
                {
                    // there is already a proxy for this impl
                    // only set the status to read-only if the proxy is read-only
                    isReallyReadOnly = ((INHibernateProxy)proxy).HibernateLazyInitializer.ReadOnly;
                }
            }

            if (isReallyReadOnly)
            {
                //no need to take a snapshot - this is a
                //performance optimization, but not really
                //important, except for entities with huge
                //mutable property values
                persistenceContext.SetEntryStatus(entityEntry, Status.ReadOnly);
            }
            else
            {
                //take a snapshot
                TypeHelper.DeepCopy(hydratedState, persister.PropertyTypes, persister.PropertyUpdateability, hydratedState, session);
                persistenceContext.SetEntryStatus(entityEntry, Status.Loaded);
            }

            persister.AfterInitialize(entity, session);

            if (session.IsEventSource)
            {
                postLoadEvent.Entity    = entity;
                postLoadEvent.Id        = id;
                postLoadEvent.Persister = persister;
                IPostLoadEventListener[] listeners = session.Listeners.PostLoadEventListeners;
                for (int i = 0; i < listeners.Length; i++)
                {
                    listeners[i].OnPostLoad(postLoadEvent);
                }
            }

            if (log.IsDebugEnabled())
            {
                log.Debug("done materializing entity {0}", MessageHelper.InfoString(persister, id, session.Factory));
            }

            if (stopWatch != null)
            {
                stopWatch.Stop();
                factory.StatisticsImplementor.LoadEntity(persister.EntityName, stopWatch.Elapsed);
            }
        }
 public static void AddUninitializedCachedEntity(EntityKey key, object obj, IEntityPersister persister, LockMode lockMode, bool lazyPropertiesAreUnfetched, object version, ISessionImplementor session)
 {
     session.PersistenceContext.AddEntity(obj, Status.Loading, null, key, version, lockMode, true, persister, false, lazyPropertiesAreUnfetched);
 }