⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 defaultflushentityeventlistener.cs

📁 NHibernate NET开发者所需的
💻 CS
📖 第 1 页 / 共 2 页
字号:
					throw new AssertionFailure("dirty, but no dirty properties");
				}
				dirtyProperties = ArrayHelper.EmptyIntArray;
			}

			// 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, entry.LoadedState, entry.Version, 
				nextVersion, entity, persister, session));

			return intercepted;
		}

		protected virtual void Validate(object entity, IEntityPersister persister, Status status, EntityMode entityMode)
		{
			// validate() instances of Validatable
			if (status == Status.Loaded && persister.ImplementsValidatable(entityMode))
			{
				((IValidatable)entity).Validate();
			}
		}

		protected virtual bool HandleInterception(FlushEntityEvent @event)
		{
			ISessionImplementor session = @event.Session;
			EntityEntry entry = @event.EntityEntry;
			IEntityPersister persister = entry.Persister;
			object entity = @event.Entity;

			//give the Interceptor a chance to modify property values
			object[] values = @event.PropertyValues;
			bool intercepted = InvokeInterceptor(session, entity, entry, values, persister);

			//now we might need to recalculate the dirtyProperties array
			if (intercepted && @event.DirtyCheckPossible && !@event.DirtyCheckHandledByInterceptor)
			{
				int[] dirtyProperties;
				if (@event.HasDatabaseSnapshot)
				{
					dirtyProperties = persister.FindModified(@event.DatabaseSnapshot, values, entity, session);
				}
				else
				{
					dirtyProperties = persister.FindDirty(values, entry.LoadedState, entity, session);
				}
				@event.DirtyProperties = dirtyProperties;
			}

			return intercepted;
		}

		protected virtual bool InvokeInterceptor(ISessionImplementor session, object entity, EntityEntry entry, object[] values, IEntityPersister persister)
		{
			return session.Interceptor.OnFlushDirty(entity, entry.Id, values, entry.LoadedState, persister.PropertyNames, persister.PropertyTypes);
		}

		private object GetNextVersion(FlushEntityEvent @event)
		{
			// Convience method to retreive an entities next version value
			EntityEntry entry = @event.EntityEntry;
			IEntityPersister persister = entry.Persister;
			if (persister.IsVersioned)
			{
				object[] values = @event.PropertyValues;

				if (entry.IsBeingReplicated)
				{
					return Versioning.GetVersion(values, persister);
				}
				else
				{
					int[] dirtyProperties = @event.DirtyProperties;

					bool isVersionIncrementRequired = IsVersionIncrementRequired(@event, entry, persister, dirtyProperties);

					object nextVersion = isVersionIncrementRequired ? 
						Versioning.Increment(entry.Version, persister.VersionType, @event.Session) : 
						entry.Version; //use the current version

					Versioning.SetVersion(values, nextVersion, persister);

					return nextVersion;
				}
			}
			else
			{
				return null;
			}
		}

		private bool IsVersionIncrementRequired(FlushEntityEvent @event, EntityEntry entry, IEntityPersister persister, int[] dirtyProperties)
		{
			bool isVersionIncrementRequired = 
				entry.Status != Status.Deleted && 
				(dirtyProperties == null || 
					Versioning.IsVersionIncrementRequired(dirtyProperties, @event.HasDirtyCollection, persister.PropertyVersionability));
			return isVersionIncrementRequired;
		}

		/// <summary> 
		/// Performs all necessary checking to determine if an entity needs an SQL update
		/// to synchronize its state to the database. Modifies the event by side-effect!
		/// Note: this method is quite slow, avoid calling if possible!
		/// </summary>
		protected bool IsUpdateNecessary(FlushEntityEvent @event)
		{
			IEntityPersister persister = @event.EntityEntry.Persister;
			Status status = @event.EntityEntry.Status;

			if (!@event.DirtyCheckPossible)
			{
				return true;
			}
			else
			{

				int[] dirtyProperties = @event.DirtyProperties;
				if (dirtyProperties != null && dirtyProperties.Length != 0)
				{
					return true; //TODO: suck into event class
				}
				else
				{
					return HasDirtyCollections(@event, persister, status);
				}
			}
		}

		private bool HasDirtyCollections(FlushEntityEvent @event, IEntityPersister persister, Status status)
		{
			if (IsCollectionDirtyCheckNecessary(persister, status))
			{
				DirtyCollectionSearchVisitor visitor = new DirtyCollectionSearchVisitor(@event.Session, persister.PropertyVersionability);
				visitor.ProcessEntityPropertyValues(@event.PropertyValues, persister.PropertyTypes);
				bool hasDirtyCollections = visitor.WasDirtyCollectionFound;
				@event.HasDirtyCollection = hasDirtyCollections;
				return hasDirtyCollections;
			}
			else
			{
				return false;
			}
		}

		private bool IsCollectionDirtyCheckNecessary(IEntityPersister persister, Status status)
		{
			return status == Status.Loaded && persister.IsVersioned && persister.HasCollections;
		}

		/// <summary> Perform a dirty check, and attach the results to the event</summary>
		protected virtual void DirtyCheck(FlushEntityEvent @event)
		{
			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 = persister.FindDirty(values, loadedState, entity, session);
				}
				else
				{
					// dirty check against the database snapshot, if possible/necessary
					object[] databaseSnapshot = GetDatabaseSnapshot(session, persister, id);
					if (databaseSnapshot != null)
					{
						dirtyProperties = persister.FindModified(databaseSnapshot, values, entity, session);
						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 object[] GetDatabaseSnapshot(ISessionImplementor session, IEntityPersister persister, object id)
		{
			if (persister.IsSelectBeforeUpdateRequired)
			{
				object[] snapshot = session.PersistenceContext.GetDatabaseSnapshot(id, persister);
				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 = new EntityKey(id, persister, session.EntityMode);
				return session.PersistenceContext.GetCachedDatabaseSnapshot(entityKey);
			}
		}

	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -