/// <summary>
		/// Constructs StandardProperty instances.
		/// </summary>
		/// <param name="name">The name by which the property can be referenced within
		/// its owner.</param>
		/// <param name="node">The node name to use for XML-based representation of this
		/// property.</param>
		/// <param name="type">The Hibernate Type of this property.</param>
		/// <param name="lazy">Should this property be handled lazily?</param>
		/// <param name="insertable">Is this property an insertable value?</param>
		/// <param name="updateable">Is this property an updateable value?</param>
		/// <param name="insertGenerated">Is this property generated in the database on insert?</param>
		/// <param name="updateGenerated">Is this property generated in the database on update?</param>
		/// <param name="nullable">Is this property a nullable value?</param>
		/// <param name="checkable">Is this property a checkable value?</param>
		/// <param name="versionable">Is this property a versionable value?</param>
		/// <param name="cascadeStyle">The cascade style for this property's value.</param>
		public StandardProperty(
			String name,
			String node,
			IType type,
			bool lazy,
			bool insertable,
			bool updateable,
			bool insertGenerated,
			bool updateGenerated,
			bool nullable,
			bool checkable,
			bool versionable,
			Cascades.CascadeStyle cascadeStyle)
			: base(name, node, type)
		{
			this.lazy = lazy;
			this.insertable = insertable;
			this.updateable = updateable;
			this.insertGenerated = insertGenerated;
			this.updateGenerated = updateGenerated;
			this.nullable = nullable;
			this.dirtyCheckable = checkable;
			this.versionable = versionable;
			this.cascadeStyle = cascadeStyle;
		}
		/// <summary>
		/// Disable outer join fetching if this loader obtains an
		/// upgrade lock mode
		/// </summary>
		protected override bool IsJoinedFetchEnabled(IAssociationType type, FetchMode config,
		                                             Cascades.CascadeStyle cascadeStyle)
		{
			return lockMode.GreaterThan(LockMode.Read) ?
			       false :
			       base.IsJoinedFetchEnabled(type, config, cascadeStyle);
		}
		public CascadeEntityJoinWalker(IOuterJoinLoadable persister, Cascades.CascadingAction action,
		                               ISessionFactoryImplementor factory)
			: base(persister, factory, CollectionHelper.EmptyMap)
		{
			this.cascadeAction = action;
			SqlStringBuilder whereCondition = WhereString(Alias, persister.IdentifierColumnNames, persister.IdentifierType, 1)
				//include the discriminator and class-level where, but not filters
				.Add(persister.FilterFragment(Alias, CollectionHelper.EmptyMap));

			InitAll(whereCondition.ToSqlString(), "", LockMode.Read);
		}
		public DynamicComponentType(
			string[ ] propertyNames,
			IType[ ] propertyTypes,
			OuterJoinFetchStrategy[ ] joinedFetch,
			Cascades.CascadeStyle[ ] cascade
			)
		{
			this.propertyNames = propertyNames;
			this.propertyTypes = propertyTypes;
			this.joinedFetch = joinedFetch;
			this.cascade = cascade;
			propertySpan = propertyTypes.Length;
		}
		protected override JoinType GetJoinType(
			IAssociationType type,
			FetchMode config,
			string path,
			string lhsTable,
			string[] lhsColumns,
			bool nullable,
			int currentDepth,
			Cascades.CascadeStyle cascadeStyle)
		{
			if (translator.IsJoin(path))
			{
				return translator.GetJoinType(path);
			}
			else
			{
				if (translator.HasProjection)
				{
					return JoinType.None;
				}
				else
				{
					FetchMode fetchMode = translator.RootCriteria
						.GetFetchMode(path);
					if (IsDefaultFetchMode(fetchMode))
					{
						return base.GetJoinType(
							type,
							config,
							path,
							lhsTable,
							lhsColumns,
							nullable,
							currentDepth, cascadeStyle
							);
					}
					else
					{
						if (fetchMode == FetchMode.Join)
						{
							IsDuplicateAssociation(lhsTable, lhsColumns, type); //deliberately ignore return value!
							return GetJoinType(nullable, currentDepth);
						}
						else
						{
							return JoinType.None;
						}
					}
				}
			}
		}
		/// <summary>
		/// Construct a virtual IdentifierProperty. 
		/// </summary>
		/// <param name="type">The Hibernate Type for the identifier property.</param>
		/// <param name="embedded">Is this an embedded identifier.</param>
		/// <param name="unsavedValue">The value which, if found as the value on the identifier
		/// property, represents new (i.e., un-saved) instances of the owning entity.</param>
		/// <param name="identifierGenerator">The generator to use for id value generation.</param>
		public IdentifierProperty(
			IType type,
			bool embedded,
			Cascades.IdentifierValue unsavedValue,
			IIdentifierGenerator identifierGenerator)
			: base(null, null, type)
		{
			this.isVirtual = true;
			this.embedded = embedded;
			this.unsavedValue = unsavedValue;
			this.identifierGenerator = identifierGenerator;
			this.identifierAssignedByInsert = identifierGenerator is IdentityGenerator;
			// TODO H3: identifierGenerator is PostInsertIdentifierGenerator;
		}
		public ComponentType(System.Type componentClass,
		                     string[] propertyNames,
		                     IGetter[] propertyGetters,
		                     ISetter[] propertySetters,
		                     // currently not used, see the comment near the end of the method body
		                     bool foundCustomAcessor,
		                     IType[] propertyTypes,
		                     bool[] nullabilities,
		                     FetchMode[] joinedFetch,
		                     Cascades.CascadeStyle[] cascade,
		                     string parentProperty)
		{
			this.componentClass = componentClass;
			this.propertyTypes = propertyTypes;
			this.propertyNullability = nullabilities;
			propertySpan = propertyNames.Length;
			getters = propertyGetters;
			setters = propertySetters;
			string[] getterNames = new string[propertySpan];
			string[] setterNames = new string[propertySpan];
			System.Type[] propTypes = new System.Type[propertySpan];
			for (int i = 0; i < propertySpan; i++)
			{
				getterNames[i] = getters[i].PropertyName;
				setterNames[i] = setters[i].PropertyName;
				propTypes[i] = getters[i].ReturnType;
			}

			if (parentProperty == null)
			{
				parentSetter = null;
				parentGetter = null;
			}
			else
			{
				IPropertyAccessor pa = PropertyAccessorFactory.GetPropertyAccessor(null);
				parentSetter = pa.GetSetter(componentClass, parentProperty);
				parentGetter = pa.GetGetter(componentClass, parentProperty);
			}
			this.propertyNames = propertyNames;
			this.cascade = cascade;
			this.joinedFetch = joinedFetch;

			if (Environment.UseReflectionOptimizer)
			{
				// NH: reflection optimizer works with custom accessors
				this.optimizer = Environment.BytecodeProvider.GetReflectionOptimizer(componentClass, getters, setters);
			}
		}
		public DynamicComponentType(
			string[] propertyNames,
			IType[] propertyTypes,
			bool[] nullabilities,
			FetchMode[] joinedFetch,
			Cascades.CascadeStyle[] cascade
			)
		{
			this.propertyNames = propertyNames;
			this.propertyTypes = propertyTypes;
			this.propertyNullability = nullabilities;
			this.joinedFetch = joinedFetch;
			this.cascade = cascade;
			propertySpan = propertyTypes.Length;
		}
		/// <summary>
		/// Constructs VersionProperty instances.
		/// </summary>
		/// <param name="name">The name by which the property can be referenced within
		/// its owner.</param>
		/// <param name="node">The node name to use for XML-based representation of this
		/// property.</param>
		/// <param name="type">The Hibernate Type of this property.</param>
		/// <param name="lazy">Should this property be handled lazily?</param>
		/// <param name="insertable">Is this property an insertable value?</param>
		/// <param name="updateable">Is this property an updateable value?</param>
		/// <param name="insertGenerated">Is this property generated in the database on insert?</param>
		/// <param name="updateGenerated">Is this property generated in the database on update?</param>
		/// <param name="nullable">Is this property a nullable value?</param>
		/// <param name="checkable">Is this property a checkable value?</param>
		/// <param name="versionable">Is this property a versionable value?</param>
		/// <param name="cascadeStyle">The cascade style for this property's value.</param>
		/// <param name="unsavedValue">The value which, if found as the value of
		/// this (i.e., the version) property, represents new (i.e., un-saved)
		/// instances of the owning entity.</param>
		public VersionProperty(
			string name,
			string node,
			IType type,
			bool lazy,
			bool insertable,
			bool updateable,
			bool insertGenerated,
			bool updateGenerated,
			bool nullable,
			bool checkable,
			bool versionable,
			Cascades.CascadeStyle cascadeStyle,
			Cascades.VersionValue unsavedValue)
			: base(
				name, node, type, lazy, insertable, updateable, insertGenerated, updateGenerated, nullable, checkable, versionable,
				cascadeStyle)
		{
			this.unsavedValue = unsavedValue;
		}
		private object SaveWithGeneratedIdentifier( object obj, Cascades.CascadingAction action, object anything )
		{
			IClassPersister persister = GetPersister( obj );
			try
			{
				object id = persister.IdentifierGenerator.Generate( this, obj );

				if( id == null )
				{
					throw new IdentifierGenerationException( string.Format( "null id generated for: {0}", obj.GetType().FullName ) );
				}
				else if( id == IdentifierGeneratorFactory.ShortCircuitIndicator )
				{
					return GetIdentifier( obj ); //yick!!
				}
				else if( id == IdentifierGeneratorFactory.IdentityColumnIndicator )
				{
					return DoSave( obj, null, persister, true, action, anything );
				}
				else
				{
					if( log.IsDebugEnabled )
					{
						log.Debug( string.Format( "generated identifier: {0}", id ) );
					}
					return DoSave( obj, id, persister, false, action, anything );
				}
			}
			catch( HibernateException )
			{
				// Do not call Convert on HibernateExceptions
				throw;
			}
			catch( Exception ex )
			{
				throw Convert( ex, "Could not save object" );
			}
		}
		protected override bool IsJoinedFetchEnabled(IAssociationType type, FetchMode config,
		                                             Cascades.CascadeStyle cascadeStyle)
		{
			return (type.IsEntityType || type.IsCollectionType) &&
			       (cascadeStyle == null || cascadeStyle.DoCascade(cascadeAction));
		}
		private object DoSave(
			object theObj,
			Key key,
			IClassPersister persister,
			bool replicate,
			bool useIdentityColumn,
			Cascades.CascadingAction cascadeAction,
			object anything )
		{
			if( persister.ImplementsValidatable )
			{
				( ( IValidatable ) theObj ).Validate();
			}

			object id;
			if( useIdentityColumn )
			{
				id = null;
				ExecuteInserts();
			}
			else
			{
				id = key.Identifier;
			}

			// Put a placeholder in entries, so we don't recurse back to try and Save() the
			// same object again. QUESTION: Should this be done before OnSave() is called?
			// likewise, should it be done before OnUpdate()?
			AddEntry( theObj, Status.Saving, null, id, null, LockMode.Write, useIdentityColumn, persister, false ); // okay if id is null here

			// cascade-save to many-to-one BEFORE the parent is saved
			cascading++;
			try
			{
				Cascades.Cascade( this, persister, theObj, cascadeAction, CascadePoint.CascadeBeforeInsertAfterDelete, anything );
			}
			finally
			{
				cascading--;
			}

			object[ ] values = persister.GetPropertyValues( theObj );
			IType[ ] types = persister.PropertyTypes;

			bool substitute = false;
			if( !replicate )
			{
				substitute = interceptor.OnSave( theObj, id, values, persister.PropertyNames, types );

				// Keep the existing version number in the case of replicate!
				if( persister.IsVersioned )
				{
					// IsUnsavedVersion bit below is NHibernate-specific
					substitute = Versioning.SeedVersion(
						values, persister.VersionProperty, persister.VersionType, persister.IsUnsavedVersion( values )
						) || substitute;
				}
			}

			if( persister.HasCollections )
			{
				// TODO: make OnReplicateVisitor extend WrapVisitor
				if( replicate )
				{
					OnReplicateVisitor visitor = new OnReplicateVisitor( this, id );
					visitor.ProcessValues( values, types );
				}
				WrapVisitor visitor2 = new WrapVisitor( this );
				// substitutes into values by side-effect
				visitor2.ProcessValues( values, types );
				substitute = substitute || visitor2.IsSubstitutionRequired;
			}

			if( substitute )
			{
				persister.SetPropertyValues( theObj, values );
			}

			TypeFactory.DeepCopy( values, types, persister.PropertyUpdateability, values );
			NullifyTransientReferences( values, types, useIdentityColumn, theObj );
			CheckNullability( values, persister, false );

			if( useIdentityColumn )
			{
				ScheduledIdentityInsertion insert = new ScheduledIdentityInsertion( values, theObj, persister, this );
				Execute( insert );
				id = insert.GeneratedId;
				persister.SetIdentifier( theObj, id );
				key = new Key( id, persister );
				CheckUniqueness( key, theObj );
			}

			object version = Versioning.GetVersion( values, persister );
			AddEntity( key, theObj );
			AddEntry( theObj, Status.Loaded, values, id, version, LockMode.Write, useIdentityColumn, persister, replicate );
			nonExists.Remove( key );

			if( !useIdentityColumn )
			{
				insertions.Add( new ScheduledInsertion( id, values, theObj, version, persister, this ) );
			}

			// cascade-save to collections AFTER the collection owner was saved
			cascading++;
			try
			{
				Cascades.Cascade( this, persister, theObj, cascadeAction, CascadePoint.CascadeAfterInsertBeforeDelete, anything );
			}
			finally
			{
				cascading--;
			}

			return id;
		}
예제 #13
0
		/// <summary>
		/// Get the join type (inner, outer, etc) or -1 if the
		/// association should not be joined. Override on
		/// subclasses.
		/// </summary>
		protected virtual JoinType GetJoinType(
			IAssociationType type,
			FetchMode config,
			String path,
			String lhsTable,
			String[] lhsColumns,
			bool nullable,
			int currentDepth,
			Cascades.CascadeStyle cascadeStyle)
		{
			if (!IsJoinedFetchEnabled(type, config, cascadeStyle))
			{
				return JoinType.None;
			}

			if (IsTooDeep(currentDepth) || IsTooManyCollections())
			{
				return JoinType.None;
			}

			bool dupe = IsDuplicateAssociation(lhsTable, lhsColumns, type);

			if (dupe)
			{
				return JoinType.None;
			}

			return GetJoinType(nullable, currentDepth);
		}
		/// <summary>
		/// We can use an inner join for first many-to-many association
		/// </summary>
		protected JoinType GetJoinType(
			IAssociationType type,
			FetchMode config,
			String path,
			ISet visitedAssociations,
			string lhsTable,
			string[] lhsColumns,
			bool nullable,
			int currentDepth,
			Cascades.CascadeStyle cascadeStyle)
		{
			JoinType joinType = base.GetJoinType(
				type,
				config,
				path,
				lhsTable,
				lhsColumns,
				nullable,
				currentDepth,
				cascadeStyle
				);

			//we can use an inner join for the many-to-many
			if (joinType == JoinType.LeftOuterJoin && "".Equals(path))
			{
				joinType = JoinType.InnerJoin;
			}
			return joinType;
		}
		/// <summary>
		/// The superclass deliberately excludes collections
		/// </summary>
		protected override bool IsJoinedFetchEnabled(IAssociationType type, FetchMode config,
		                                             Cascades.CascadeStyle cascadeStyle)
		{
			return IsJoinedFetchEnabledInMapping(config, type);
		}
		private object DoSave(
			object obj,
			object id,
			IClassPersister persister,
			bool useIdentityColumn,
			Cascades.CascadingAction cascadeAction,
			object anything )
		{
			if( log.IsDebugEnabled )
			{
				log.Debug( "saving " + MessageHelper.InfoString( persister, id ) );
			}

			Key key;
			if( useIdentityColumn )
			{
				// if the id is generated by the database, we assign the key later
				key = null;
			}
			else
			{
				key = new Key( id, persister );

				object old = GetEntity( key );
				if( old != null )
				{
					EntityEntry e = GetEntry( old );
					if( e.Status == Status.Deleted )
					{
						ForceFlush( e );
					}
					else
					{
						throw new NonUniqueObjectException( id, persister.MappedClass );
					}
				}

				persister.SetIdentifier( obj, id );
			}

			// Sub-insertions should occur before containing insertsion so
			// Try to do the callback not
			if( persister.ImplementsLifecycle )
			{
				log.Debug( "calling OnSave()" );
				if( ( ( ILifecycle ) obj ).OnSave( this ) == LifecycleVeto.Veto )
				{
					log.Debug( "insertion vetoed by OnSave()" );
					return id;
				}
			}

			return DoSave( obj, key, persister, false, useIdentityColumn, cascadeAction, anything );
		}
예제 #17
0
 public override ICollection CascadableChildrenCollection(PersistentCollectionType collectionType, object collection)
 {
     return(Cascades.GetLoadedElementsCollection(collectionType, collection));
 }
예제 #18
0
 public override ICollection CascadableChildrenCollection(PersistentCollectionType collectionType, object collection)
 {
     // saves / updates don't cascade to uninitialized collections
     return(Cascades.GetLoadedElementsCollection(collectionType, collection));
 }
예제 #19
0
		/// <summary>
		/// Override on subclasses to enable or suppress joining
		/// of certain association types
		/// </summary>
		protected virtual bool IsJoinedFetchEnabled(IAssociationType type, FetchMode config,
		                                            Cascades.CascadeStyle cascadeStyle)
		{
			return type.IsEntityType && IsJoinedFetchEnabledInMapping(config, type);
		}