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

📄 abstractsaveeventlistener.cs

📁 NHibernate NET开发者所需的
💻 CS
📖 第 1 页 / 共 2 页
字号:
using System;
using System.Collections;
using log4net;
using NHibernate.Action;
using NHibernate.Classic;
using NHibernate.Engine;
using NHibernate.Id;
using NHibernate.Impl;
using NHibernate.Intercept;
using NHibernate.Persister.Entity;
using NHibernate.Type;
using Status=NHibernate.Engine.Status;

namespace NHibernate.Event.Default
{
	public enum EntityState
	{
		Undefined = -1,
		Persistent = 0,
		Transient = 1,
		Detached = 2,
		Deleted = 3
	}

	/// <summary> 
	/// A convenience bas class for listeners responding to save events. 
	/// </summary>
	[Serializable]
	public abstract class AbstractSaveEventListener : AbstractReassociateEventListener
	{
		private static readonly ILog log = LogManager.GetLogger(typeof(AbstractSaveEventListener));

		protected virtual bool? AssumedUnsaved
		{
			get { return null; }
		}

		protected abstract CascadingAction CascadeAction { get;}

		/// <summary> 
		/// After the save, will te version number be incremented
		/// if the instance is modified? 
		/// </summary>
		/// <returns> True if the version will be incremented on an entity change after save; false otherwise. </returns>
		protected virtual bool VersionIncrementDisabled
		{
			get { return false; }
		}

		protected virtual bool InvokeSaveLifecycle(object entity, IEntityPersister persister, IEventSource source)
		{
			// Sub-insertions should occur before containing insertion so
			// Try to do the callback now
			if (persister.ImplementsLifecycle(source.EntityMode))
			{
				log.Debug("calling OnSave()");
				if (((ILifecycle)entity).OnSave(source) == LifecycleVeto.Veto)
				{
					log.Debug("insertion vetoed by OnSave()");
					return true;
				}
			}
			return false;
		}

		protected virtual void Validate(object entity, IEntityPersister persister, IEventSource source)
		{
			if (persister.ImplementsValidatable(source.EntityMode))
			{
				((IValidatable)entity).Validate();
			}
		}

		/// <summary> 
		/// Prepares the save call using the given requested id. 
		/// </summary>
		/// <param name="entity">The entity to be saved. </param>
		/// <param name="requestedId">The id to which to associate the entity. </param>
		/// <param name="entityName">The name of the entity being saved. </param>
		/// <param name="anything">Generally cascade-specific information. </param>
		/// <param name="source">The session which is the source of this save event. </param>
		/// <returns> The id used to save the entity. </returns>
		protected virtual object SaveWithRequestedId(object entity, object requestedId, string entityName, object anything, IEventSource source)
		{
			return PerformSave(entity, requestedId, source.GetEntityPersister(entity), false, anything, source, true);
		}

		/// <summary> 
		/// Prepares the save call using a newly generated id. 
		/// </summary>
		/// <param name="entity">The entity to be saved </param>
		/// <param name="entityName">The entity-name for the entity to be saved </param>
		/// <param name="anything">Generally cascade-specific information. </param>
		/// <param name="source">The session which is the source of this save event. </param>
		/// <param name="requiresImmediateIdAccess">
		/// does the event context require
		/// access to the identifier immediately after execution of this method (if
		/// not, post-insert style id generators may be postponed if we are outside
		/// a transaction). 
		/// </param>
		/// <returns> 
		/// The id used to save the entity; may be null depending on the
		/// type of id generator used and the requiresImmediateIdAccess value
		/// </returns>
		protected virtual object SaveWithGeneratedId(object entity, string entityName, object anything, IEventSource source, bool requiresImmediateIdAccess)
		{
			IEntityPersister persister = source.GetEntityPersister(entity);
			object generatedId = persister.IdentifierGenerator.Generate(source, entity);
			if (generatedId == null)
			{
				throw new IdentifierGenerationException("null id generated for:" + entity.GetType());
			}
			else if (generatedId == IdentifierGeneratorFactory.ShortCircuitIndicator)
			{
				return source.GetIdentifier(entity);
			}
			else if (generatedId == IdentifierGeneratorFactory.PostInsertIndicator)
			{
				return PerformSave(entity, null, persister, true, anything, source, requiresImmediateIdAccess);
			}
			else
			{
				if (log.IsDebugEnabled)
				{
					log.Debug(string.Format("generated identifier: {0}, using strategy: {1}",
						persister.IdentifierType.ToLoggableString(generatedId, source.Factory),
						persister.IdentifierGenerator.GetType().FullName));
				}
				return PerformSave(entity, generatedId, persister, false, anything, source, true);
			}
		}

		/// <summary> 
		/// Prepares the save call by checking the session caches for a pre-existing
		/// entity and performing any lifecycle callbacks. 
		/// </summary>
		/// <param name="entity">The entity to be saved. </param>
		/// <param name="id">The id by which to save the entity. </param>
		/// <param name="persister">The entity's persister instance. </param>
		/// <param name="useIdentityColumn">Is an identity column being used? </param>
		/// <param name="anything">Generally cascade-specific information. </param>
		/// <param name="source">The session from which the event originated. </param>
		/// <param name="requiresImmediateIdAccess">
		/// does the event context require
		/// access to the identifier immediately after execution of this method (if
		/// not, post-insert style id generators may be postponed if we are outside
		/// a transaction). 
		/// </param>
		/// <returns> 
		/// The id used to save the entity; may be null depending on the
		/// type of id generator used and the requiresImmediateIdAccess value
		/// </returns>
		protected virtual object PerformSave(object entity, object id, IEntityPersister persister, bool useIdentityColumn, object anything, IEventSource source, bool requiresImmediateIdAccess)
		{
			if (log.IsDebugEnabled)
			{
				log.Debug("saving " + MessageHelper.InfoString(persister, id, source.Factory));
			}

			EntityKey key;
			if (!useIdentityColumn)
			{
				key = new EntityKey(id, persister, source.EntityMode);
				object old = source.PersistenceContext.GetEntity(key);
				if (old != null)
				{
					if (source.PersistenceContext.GetEntry(old).Status == Status.Deleted)
					{
						source.ForceFlush(source.PersistenceContext.GetEntry(old));
					}
					else
					{
						throw new NonUniqueObjectException(id, persister.EntityName);
					}
				}
				persister.SetIdentifier(entity, id, source.EntityMode);
			}
			else
			{
				key = null;
			}

			if (InvokeSaveLifecycle(entity, persister, source))
			{
				return id; //EARLY EXIT
			}
			return PerformSaveOrReplicate(entity, key, persister, useIdentityColumn, anything, source, requiresImmediateIdAccess);
		}

		/// <summary> 
		/// Performs all the actual work needed to save an entity (well to get the save moved to
		/// the execution queue). 
		/// </summary>
		/// <param name="entity">The entity to be saved </param>
		/// <param name="key">The id to be used for saving the entity (or null, in the case of identity columns) </param>
		/// <param name="persister">The entity's persister instance. </param>
		/// <param name="useIdentityColumn">Should an identity column be used for id generation? </param>
		/// <param name="anything">Generally cascade-specific information. </param>
		/// <param name="source">The session which is the source of the current event. </param>
		/// <param name="requiresImmediateIdAccess">
		/// Is access to the identifier required immediately
		/// after the completion of the save?  persist(), for example, does not require this... 
		/// </param>
		/// <returns> 
		/// The id used to save the entity; may be null depending on the
		/// type of id generator used and the requiresImmediateIdAccess value
		/// </returns>
		protected virtual object PerformSaveOrReplicate(object entity, EntityKey key, IEntityPersister persister, bool useIdentityColumn, object anything, IEventSource source, bool requiresImmediateIdAccess)
		{
			Validate(entity, persister, source);

			object id = key == null ? null : key.Identifier;

			// NH Different behavior (shouldDelayIdentityInserts=false anyway)
			//bool inTxn = source.ConnectionManager.IsInActiveTransaction;
			//bool shouldDelayIdentityInserts = !inTxn && !requiresImmediateIdAccess;
			bool shouldDelayIdentityInserts = false;

			// Put a placeholder in entries, so we don't recurse back and try to save() the
			// same object again. QUESTION: should this be done before onSave() is called?
			// likewise, should it be done before onUpdate()?

⌨️ 快捷键说明

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