Пример #1
0
		public void CreatePropertyRefConstraints(IDictionary<string, PersistentClass> persistentClasses)
		{
			if (!string.IsNullOrEmpty(referencedPropertyName))
			{
				if (string.IsNullOrEmpty(ReferencedEntityName))
					throw new MappingException(
						string.Format("ReferencedEntityName not specified for property '{0}' on entity {1}", ReferencedPropertyName, this));

				PersistentClass pc;
				persistentClasses.TryGetValue(ReferencedEntityName, out pc);
				if (pc == null)
					throw new MappingException(string.Format("Could not find referenced entity '{0}' on {1}", ReferencedEntityName, this));

				Property property = pc.GetReferencedProperty(ReferencedPropertyName);
				if (property == null)
					throw new MappingException("Could not find property " + ReferencedPropertyName + " on " + ReferencedEntityName);

				if (!HasFormula && !"none".Equals(ForeignKeyName, StringComparison.InvariantCultureIgnoreCase))
				{

					IEnumerable<Column> ce = new SafetyEnumerable<Column>(property.ColumnIterator);

					// NH : The four lines below was added to ensure that related columns have same length,
					// like ForeignKey.AlignColumns() do
					IEnumerator<Column> fkCols = ConstraintColumns.GetEnumerator();
					IEnumerator<Column> pkCols = ce.GetEnumerator();
					while (fkCols.MoveNext() && pkCols.MoveNext())
						fkCols.Current.Length = pkCols.Current.Length;

					ForeignKey fk =
						Table.CreateForeignKey(ForeignKeyName, ConstraintColumns, ((EntityType) Type).GetAssociatedEntityName(), ce);
					fk.CascadeDeleteEnabled = IsCascadeDeleteEnabled;
				}
			}
		}
        public void MixedWithNulls()
        {
            IList <IAType> l = new List <IAType>();

            l.Add(new AClass());
            l.Add(null);
            l.Add(new AClass());
            l.Add(new BClass());
            l.Add(new AClass());
            IEnumerable <AClass> eAClass = new SafetyEnumerable <AClass>(l);
            int i = 0;

            foreach (IAType aClass in eAClass)
            {
                ++i;
            }
            Assert.AreEqual(4, i);

            IEnumerable <BClass> eBClass = new SafetyEnumerable <BClass>(l);

            i = 0;
            foreach (IAType aClass in eBClass)
            {
                ++i;
            }
            Assert.AreEqual(2, i);
        }
        public void RecyclingCollection()
        {
            IList <IAType> l = new List <IAType>();

            l.Add(new AClass());
            l.Add(new BClass());
            l.Add(new AClass());
            l.Add(new BClass());
            l.Add(new AClass());
            IEnumerable <AClass> eAClass = new SafetyEnumerable <AClass>(l);
            int i = 0;

            foreach (IAType aClass in eAClass)
            {
                ++i;
            }
            Assert.AreEqual(3, i);

            i = 0;
            foreach (IAType aClass in eAClass)
            {
                ++i;
            }
            Assert.AreEqual(3, i);
        }
		public void RecyclingCollection()
		{
			IList<IAType> l = new List<IAType>();
			l.Add(new AClass());
			l.Add(new BClass());
			l.Add(new AClass());
			l.Add(new BClass());
			l.Add(new AClass());
			IEnumerable<AClass> eAClass = new SafetyEnumerable<AClass>(l);
			int i = 0;
			foreach (IAType aClass in eAClass) ++i;
			Assert.AreEqual(3, i);

			i = 0;
			foreach (IAType aClass in eAClass) ++i;
			Assert.AreEqual(3, i);
		}
		public void MixedWithNulls()
		{
			IList<IAType> l = new List<IAType>();
			l.Add(new AClass());
			l.Add(null);
			l.Add(new AClass());
			l.Add(new BClass());
			l.Add(new AClass());
			IEnumerable<AClass> eAClass = new SafetyEnumerable<AClass>(l);
			int i = 0;
			foreach (IAType aClass in eAClass) ++i;
			Assert.AreEqual(4, i);

			IEnumerable<BClass> eBClass = new SafetyEnumerable<BClass>(l);
			i = 0;
			foreach (IAType aClass in eBClass) ++i;
			Assert.AreEqual(2, i);
		}
Пример #6
0
        public void CreatePropertyRefConstraints(IDictionary <string, PersistentClass> persistentClasses)
        {
            if (!string.IsNullOrEmpty(referencedPropertyName))
            {
                if (string.IsNullOrEmpty(ReferencedEntityName))
                {
                    throw new MappingException(
                              string.Format("ReferencedEntityName not specified for property '{0}' on entity {1}", ReferencedPropertyName, this));
                }

                PersistentClass pc;
                persistentClasses.TryGetValue(ReferencedEntityName, out pc);
                if (pc == null)
                {
                    throw new MappingException(string.Format("Could not find referenced entity '{0}' on {1}", ReferencedEntityName, this));
                }

                Property property = pc.GetReferencedProperty(ReferencedPropertyName);
                if (property == null)
                {
                    throw new MappingException("Could not find property " + ReferencedPropertyName + " on " + ReferencedEntityName);
                }

                if (!HasFormula && !"none".Equals(ForeignKeyName, StringComparison.InvariantCultureIgnoreCase))
                {
                    IEnumerable <Column> ce = new SafetyEnumerable <Column>(property.ColumnIterator);

                    // NH : The four lines below was added to ensure that related columns have same length,
                    // like ForeignKey.AlignColumns() do
                    using (var fkCols = ConstraintColumns.GetEnumerator())
                        using (var pkCols = ce.GetEnumerator())
                        {
                            while (fkCols.MoveNext() && pkCols.MoveNext())
                            {
                                fkCols.Current.Length = pkCols.Current.Length;
                            }
                        }

                    ForeignKey fk =
                        Table.CreateForeignKey(ForeignKeyName, ConstraintColumns, ((EntityType)Type).GetAssociatedEntityName(), ce);
                    fk.CascadeDeleteEnabled = IsCascadeDeleteEnabled;
                }
            }
        }
Пример #7
0
        public void CreatePropertyRefConstraints(IDictionary <string, PersistentClass> persistentClasses)
        {
            if (!string.IsNullOrEmpty(referencedPropertyName))
            {
                if (string.IsNullOrEmpty(ReferencedEntityName))
                {
                    throw new MappingException(
                              string.Format("ReferencedEntityName not specified for property '{0}' on entity {1}", ReferencedPropertyName, this));
                }

                PersistentClass pc;
                persistentClasses.TryGetValue(ReferencedEntityName, out pc);
                if (pc == null)
                {
                    throw new MappingException(string.Format("Could not find referenced entity '{0}' on {1}", ReferencedEntityName, this));
                }

                Property property = pc.GetReferencedProperty(ReferencedPropertyName);
                if (property == null)
                {
                    throw new MappingException("Could not find property " + ReferencedPropertyName + " on " + ReferencedEntityName);
                }

                if (!HasFormula && !"none".Equals(ForeignKeyName, StringComparison.OrdinalIgnoreCase))
                {
                    IEnumerable <Column> ce = new SafetyEnumerable <Column>(property.ColumnIterator);

                    // NH : Ensure that related columns have same length
                    ForeignKey.AlignColumns(ConstraintColumns, ce);

                    ForeignKey fk =
                        Table.CreateForeignKey(ForeignKeyName, ConstraintColumns, ((EntityType)Type).GetAssociatedEntityName(), ce);
                    fk.CascadeDeleteEnabled = IsCascadeDeleteEnabled;
                }
            }
        }
		public SingleTableEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache,
																			ISessionFactoryImplementor factory, IMapping mapping)
			: base(persistentClass, cache, factory)
		{
			#region CLASS + TABLE

			joinSpan = persistentClass.JoinClosureSpan + 1;
			qualifiedTableNames = new string[joinSpan];
			isInverseTable = new bool[joinSpan];
			isNullableTable = new bool[joinSpan];
			keyColumnNames = new string[joinSpan][];
			Table table = persistentClass.RootTable;
			qualifiedTableNames[0] =
				table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
			isInverseTable[0] = false;
			isNullableTable[0] = false;
			keyColumnNames[0] = IdentifierColumnNames;
			cascadeDeleteEnabled = new bool[joinSpan];

			// Custom sql
			customSQLInsert = new SqlString[joinSpan];
			customSQLUpdate = new SqlString[joinSpan];
			customSQLDelete = new SqlString[joinSpan];
			insertCallable = new bool[joinSpan];
			updateCallable = new bool[joinSpan];
			deleteCallable = new bool[joinSpan];
			insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];
			updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];
			deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];

			customSQLInsert[0] = persistentClass.CustomSQLInsert;
			insertCallable[0] = customSQLInsert[0] != null && persistentClass.IsCustomInsertCallable;
			insertResultCheckStyles[0] = persistentClass.CustomSQLInsertCheckStyle
																	 ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[0], insertCallable[0]);
			customSQLUpdate[0] = persistentClass.CustomSQLUpdate;
			updateCallable[0] = customSQLUpdate[0] != null && persistentClass.IsCustomUpdateCallable;
			updateResultCheckStyles[0] = persistentClass.CustomSQLUpdateCheckStyle
																	 ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[0], updateCallable[0]);
			customSQLDelete[0] = persistentClass.CustomSQLDelete;
			deleteCallable[0] = customSQLDelete[0] != null && persistentClass.IsCustomDeleteCallable;
			deleteResultCheckStyles[0] = persistentClass.CustomSQLDeleteCheckStyle
																	 ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[0], deleteCallable[0]);

			#endregion

			#region JOINS
			int j = 1;
			foreach (Join join in persistentClass.JoinClosureIterator)
			{
				qualifiedTableNames[j] = join.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
				isInverseTable[j] = join.IsInverse;
				isNullableTable[j] = join.IsOptional;
				cascadeDeleteEnabled[j] = join.Key.IsCascadeDeleteEnabled && factory.Dialect.SupportsCascadeDelete;

				customSQLInsert[j] = join.CustomSQLInsert;
				insertCallable[j] = customSQLInsert[j] != null && join.IsCustomInsertCallable;
				insertResultCheckStyles[j] = join.CustomSQLInsertCheckStyle
																		 ??
																		 ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[j], insertCallable[j]);
				customSQLUpdate[j] = join.CustomSQLUpdate;
				updateCallable[j] = customSQLUpdate[j] != null && join.IsCustomUpdateCallable;
				updateResultCheckStyles[j] = join.CustomSQLUpdateCheckStyle
																		 ??
																		 ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[j], updateCallable[j]);
				customSQLDelete[j] = join.CustomSQLDelete;
				deleteCallable[j] = customSQLDelete[j] != null && join.IsCustomDeleteCallable;
				deleteResultCheckStyles[j] = join.CustomSQLDeleteCheckStyle
																		 ??
																		 ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[j], deleteCallable[j]);

				IEnumerable<Column> enumerableKeyCol = new SafetyEnumerable<Column>(join.Key.ColumnIterator);
				List<string> kcName = new List<string>(join.Key.ColumnSpan);
				foreach (Column col in enumerableKeyCol)
					kcName.Add(col.GetQuotedName(factory.Dialect));

				keyColumnNames[j] = kcName.ToArray();

				j++;
			}

			constraintOrderedTableNames = new string[qualifiedTableNames.Length];
			constraintOrderedKeyColumnNames = new string[qualifiedTableNames.Length][];
			for (int i = qualifiedTableNames.Length - 1, position = 0; i >= 0; i--, position++)
			{
				constraintOrderedTableNames[position] = qualifiedTableNames[i];
				constraintOrderedKeyColumnNames[position] = keyColumnNames[i];
			}

			spaces = ArrayHelper.Join(qualifiedTableNames, ArrayHelper.ToStringArray(persistentClass.SynchronizedTables));

			bool lazyAvailable = IsInstrumented(EntityMode.Poco);

			bool hasDeferred = false;
			List<string> subclassTables = new List<string>();
			List<string[]> joinKeyColumns = new List<string[]>();
			List<bool> isConcretes = new List<bool>();
			List<bool> isDeferreds = new List<bool>();
			List<bool> isInverses = new List<bool>();
			List<bool> isNullables = new List<bool>();
			List<bool> isLazies = new List<bool>();
			subclassTables.Add(qualifiedTableNames[0]);
			joinKeyColumns.Add(IdentifierColumnNames);
			isConcretes.Add(true);
			isDeferreds.Add(false);
			isInverses.Add(false);
			isNullables.Add(false);
			isLazies.Add(false);
			foreach (Join join in persistentClass.SubclassJoinClosureIterator)
			{
				isConcretes.Add(persistentClass.IsClassOrSuperclassJoin(join));
				isDeferreds.Add(join.IsSequentialSelect);
				isInverses.Add(join.IsInverse);
				isNullables.Add(join.IsOptional);
				isLazies.Add(lazyAvailable && join.IsLazy);
				if (join.IsSequentialSelect && !persistentClass.IsClassOrSuperclassJoin(join))
					hasDeferred = true;
				subclassTables.Add(join.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName));
				IEnumerable<Column> enumerableKeyCol = new SafetyEnumerable<Column>(join.Key.ColumnIterator);
				List<string> keyCols = new List<string>(join.Key.ColumnSpan);
				foreach (Column col in enumerableKeyCol)
					keyCols.Add(col.GetQuotedName(factory.Dialect));

				joinKeyColumns.Add(keyCols.ToArray());
			}

			subclassTableSequentialSelect = isDeferreds.ToArray();
			subclassTableNameClosure = subclassTables.ToArray();
			subclassTableIsLazyClosure = isLazies.ToArray();
			subclassTableKeyColumnClosure = joinKeyColumns.ToArray();
			isClassOrSuperclassTable = isConcretes.ToArray();
			isInverseSubclassTable = isInverses.ToArray();
			isNullableSubclassTable = isNullables.ToArray();
			hasSequentialSelects = hasDeferred;

			#endregion

			#region DISCRIMINATOR

			if (persistentClass.IsPolymorphic)
			{
				IValue discrimValue = persistentClass.Discriminator;
				if (discrimValue == null)
					throw new MappingException("Discriminator mapping required for single table polymorphic persistence");

				forceDiscriminator = persistentClass.IsForceDiscriminator;
				IEnumerator<ISelectable> iSel = discrimValue.ColumnIterator.GetEnumerator();
				iSel.MoveNext();
				ISelectable selectable = iSel.Current;
				if (discrimValue.HasFormula)
				{
					Formula formula = (Formula)selectable;
					discriminatorFormula = formula.FormulaString;
					discriminatorFormulaTemplate = formula.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry);
					discriminatorColumnName = null;
					discriminatorAlias = Discriminator_Alias;
				}
				else
				{
					Column column = (Column)selectable;
					discriminatorColumnName = column.GetQuotedName(factory.Dialect);
					discriminatorAlias = column.GetAlias(factory.Dialect, persistentClass.RootTable);
					discriminatorFormula = null;
					discriminatorFormulaTemplate = null;
				}
				discriminatorType = persistentClass.Discriminator.Type;
				if (persistentClass.IsDiscriminatorValueNull)
				{
					discriminatorValue = NullDiscriminator;
					discriminatorSQLValue = InFragment.Null;
					discriminatorInsertable = false;
				}
				else if (persistentClass.IsDiscriminatorValueNotNull)
				{
					discriminatorValue = NotNullDiscriminator;
					discriminatorSQLValue = InFragment.NotNull;
					discriminatorInsertable = false;
				}
				else
				{
					discriminatorInsertable = persistentClass.IsDiscriminatorInsertable && !discrimValue.HasFormula;
					try
					{
						IDiscriminatorType dtype = (IDiscriminatorType)discriminatorType;
						discriminatorValue = dtype.StringToObject(persistentClass.DiscriminatorValue);
						discriminatorSQLValue = dtype.ObjectToSQLString(discriminatorValue, factory.Dialect);
					}
					catch (InvalidCastException cce)
					{
						throw new MappingException(
							string.Format("Illegal discriminator type: {0} of entity {1}", discriminatorType.Name, persistentClass.EntityName), cce);
					}
					catch (Exception e)
					{
						throw new MappingException("Could not format discriminator value to SQL string of entity " + persistentClass.EntityName, e);
					}
				}
			}
			else
			{
				forceDiscriminator = false;
				discriminatorInsertable = false;
				discriminatorColumnName = null;
				discriminatorAlias = null;
				discriminatorType = null;
				discriminatorValue = null;
				discriminatorSQLValue = null;
				discriminatorFormula = null;
				discriminatorFormulaTemplate = null;
			}

			#endregion

			#region PROPERTIES

			propertyTableNumbers = new int[PropertySpan];
			int i2 = 0;
			foreach (Property prop in persistentClass.PropertyClosureIterator)
			{
				propertyTableNumbers[i2++] = persistentClass.GetJoinNumber(prop);
			}

			List<int> columnJoinNumbers = new List<int>();
			List<int> formulaJoinedNumbers = new List<int>();
			List<int> propertyJoinNumbers = new List<int>();
			foreach (Property prop in persistentClass.SubclassPropertyClosureIterator)
			{
				int join = persistentClass.GetJoinNumber(prop);
				propertyJoinNumbers.Add(join);

				//propertyTableNumbersByName.put( prop.getName(), join );
				propertyTableNumbersByNameAndSubclass[prop.PersistentClass.EntityName + '.' + prop.Name] = join;
				foreach (ISelectable thing in prop.ColumnIterator)
				{
					if (thing.IsFormula)
						formulaJoinedNumbers.Add(join);
					else
						columnJoinNumbers.Add(join);
				}
			}

			subclassColumnTableNumberClosure = columnJoinNumbers.ToArray();
			subclassFormulaTableNumberClosure = formulaJoinedNumbers.ToArray();
			subclassPropertyTableNumberClosure = propertyJoinNumbers.ToArray();

			int subclassSpan = persistentClass.SubclassSpan + 1;
			subclassClosure = new string[subclassSpan];
			subclassClosure[0] = EntityName;
			if (persistentClass.IsPolymorphic)
				subclassesByDiscriminatorValue[discriminatorValue] = EntityName;

			#endregion

			#region SUBCLASSES
			if (persistentClass.IsPolymorphic)
			{
				int k = 1;
				foreach (Subclass sc in persistentClass.SubclassIterator)
				{
					subclassClosure[k++] = sc.EntityName;
					if (sc.IsDiscriminatorValueNull)
					{
						subclassesByDiscriminatorValue[NullDiscriminator] = sc.EntityName;
					}
					else if (sc.IsDiscriminatorValueNotNull)
					{
						subclassesByDiscriminatorValue[NotNullDiscriminator] = sc.EntityName;
					}
					else
					{
						if (discriminatorType == null)
							throw new MappingException("Not available discriminator type of entity " + persistentClass.EntityName);
						try
						{
							IDiscriminatorType dtype = (IDiscriminatorType)discriminatorType;
							subclassesByDiscriminatorValue[dtype.StringToObject(sc.DiscriminatorValue)] = sc.EntityName;
						}
						catch (InvalidCastException cce)
						{
							throw new MappingException(
								string.Format("Illegal discriminator type: {0} of entity {1}", discriminatorType.Name, persistentClass.EntityName), cce);
						}
						catch (Exception e)
						{
							throw new MappingException("Error parsing discriminator value of entity " + persistentClass.EntityName, e);
						}
					}
				}
			}

			#endregion

			InitLockers();

			InitSubclassPropertyAliasesMap(persistentClass);

			PostConstruct(mapping);
		}
		/// <summary>
		/// Constructs the NormalizedEntityPerister for the PersistentClass.
		/// </summary>
		/// <param name="persistentClass">The PersistentClass to create the EntityPersister for.</param>
		/// <param name="cache">The configured <see cref="ICacheConcurrencyStrategy" />.</param>
		/// <param name="factory">The SessionFactory that this EntityPersister will be stored in.</param>
		/// <param name="mapping">The mapping used to retrieve type information.</param>
		public JoinedSubclassEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache,
											 ISessionFactoryImplementor factory, IMapping mapping)
			: base(persistentClass, cache, factory)
		{
			#region DISCRIMINATOR

			if (persistentClass.IsPolymorphic)
			{
				try
				{
					discriminatorValue = persistentClass.SubclassId;
					discriminatorSQLString = discriminatorValue.ToString();
				}
				catch (Exception e)
				{
					throw new MappingException("Could not format discriminator value to SQL string", e);
				}
			}
			else
			{
				discriminatorValue = null;
				discriminatorSQLString = null;
			}

			if (OptimisticLockMode > Versioning.OptimisticLock.Version)
				throw new MappingException(string.Format("optimistic-lock=all|dirty not supported for joined-subclass mappings [{0}]", EntityName));

			#endregion

			#region MULTITABLES
			int idColumnSpan = IdentifierColumnSpan;

			List<string> tables = new List<string>();
			List<string[]> keyColumns = new List<string[]>();
			List<bool> cascadeDeletes = new List<bool>();
			IEnumerator<IKeyValue> kiter = persistentClass.KeyClosureIterator.GetEnumerator();
			foreach (Table tab in persistentClass.TableClosureIterator)
			{
				kiter.MoveNext();
				IKeyValue key = kiter.Current;
				string tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
				tables.Add(tabname);

				List<string> keyCols = new List<string>(idColumnSpan);
				IEnumerable<Column> enumerableKCols = new SafetyEnumerable<Column>(key.ColumnIterator);
				foreach (Column kcol in enumerableKCols)
					keyCols.Add(kcol.GetQuotedName(factory.Dialect));

				keyColumns.Add(keyCols.ToArray());
				cascadeDeletes.Add(key.IsCascadeDeleteEnabled && factory.Dialect.SupportsCascadeDelete);				
			}
			naturalOrderTableNames = tables.ToArray();
			naturalOrderTableKeyColumns = keyColumns.ToArray();
			naturalOrderCascadeDeleteEnabled = cascadeDeletes.ToArray();

			List<string> subtables = new List<string>();
			List<bool> isConcretes = new List<bool>();
			keyColumns = new List<string[]>();
			foreach (Table tab in persistentClass.SubclassTableClosureIterator)
			{
				isConcretes.Add(persistentClass.IsClassOrSuperclassTable(tab));
				string tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
				subtables.Add(tabname);
				List<string> key = new List<string>(idColumnSpan);
				foreach (Column column in tab.PrimaryKey.ColumnIterator)
					key.Add(column.GetQuotedName(factory.Dialect));

				keyColumns.Add(key.ToArray());				
			}
			subclassTableNameClosure = subtables.ToArray();
			subclassTableKeyColumnClosure = keyColumns.ToArray();
			isClassOrSuperclassTable = isConcretes.ToArray();

			constraintOrderedTableNames = new string[subclassTableNameClosure.Length];
			constraintOrderedKeyColumnNames = new string[subclassTableNameClosure.Length][];
			int currentPosition = 0;
			for (int i = subclassTableNameClosure.Length - 1; i >= 0; i--, currentPosition++)
			{
				constraintOrderedTableNames[currentPosition] = subclassTableNameClosure[i];
				constraintOrderedKeyColumnNames[currentPosition] = subclassTableKeyColumnClosure[i];
			}

			tableSpan = naturalOrderTableNames.Length;
			tableNames = Reverse(naturalOrderTableNames);
			tableKeyColumns = Reverse(naturalOrderTableKeyColumns);
			Reverse(subclassTableNameClosure, tableSpan);
			Reverse(subclassTableKeyColumnClosure, tableSpan);

			spaces = ArrayHelper.Join(tableNames, persistentClass.SynchronizedTables.ToArray());

			// Custom sql
			customSQLInsert = new SqlString[tableSpan];
			customSQLUpdate = new SqlString[tableSpan];
			customSQLDelete = new SqlString[tableSpan];
			insertCallable = new bool[tableSpan];
			updateCallable = new bool[tableSpan];
			deleteCallable = new bool[tableSpan];
			insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];
			updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];
			deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];

			PersistentClass pc = persistentClass;
			int jk = tableSpan - 1;
			while (pc != null)
			{
				customSQLInsert[jk] = pc.CustomSQLInsert;
				insertCallable[jk] = customSQLInsert[jk] != null && pc.IsCustomInsertCallable;
				insertResultCheckStyles[jk] = pc.CustomSQLInsertCheckStyle
											  ??
											  ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[jk], insertCallable[jk]);
				customSQLUpdate[jk] = pc.CustomSQLUpdate;
				updateCallable[jk] = customSQLUpdate[jk] != null && pc.IsCustomUpdateCallable;
				updateResultCheckStyles[jk] = pc.CustomSQLUpdateCheckStyle
											  ??
											  ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[jk], updateCallable[jk]);
				customSQLDelete[jk] = pc.CustomSQLDelete;
				deleteCallable[jk] = customSQLDelete[jk] != null && pc.IsCustomDeleteCallable;
				deleteResultCheckStyles[jk] = pc.CustomSQLDeleteCheckStyle
											  ??
											  ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[jk], deleteCallable[jk]);
				jk--;
				pc = pc.Superclass;
			}
			if (jk != -1)
			{
				throw new AssertionFailure("Tablespan does not match height of joined-subclass hierarchy.");
			}

			#endregion

			#region PROPERTIES

			int hydrateSpan = PropertySpan;
			naturalOrderPropertyTableNumbers = new int[hydrateSpan];
			propertyTableNumbers = new int[hydrateSpan];
			int i2 = 0;
			foreach (Property prop in persistentClass.PropertyClosureIterator)
			{
				string tabname = prop.Value.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
				propertyTableNumbers[i2] = GetTableId(tabname, tableNames);
				naturalOrderPropertyTableNumbers[i2] = GetTableId(tabname, naturalOrderTableNames);
				i2++;
			}

			// subclass closure properties
			List<int> columnTableNumbers = new List<int>();
			List<int> formulaTableNumbers = new List<int>();
			List<int> propTableNumbers = new List<int>();
			foreach (Property prop in persistentClass.SubclassPropertyClosureIterator)
			{
				Table tab = prop.Value.Table;
				string tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
				int tabnum = GetTableId(tabname, subclassTableNameClosure);
				propTableNumbers.Add(tabnum);

				foreach (ISelectable thing in prop.ColumnIterator)
				{
					if (thing.IsFormula)
						formulaTableNumbers.Add(tabnum);
					else
						columnTableNumbers.Add(tabnum);
				}
			}

			subclassColumnTableNumberClosure = columnTableNumbers.ToArray();
			subclassPropertyTableNumberClosure = propTableNumbers.ToArray();
			subclassFormulaTableNumberClosure = formulaTableNumbers.ToArray();
			#endregion

			#region SUBCLASSES

			int subclassSpan = persistentClass.SubclassSpan + 1;
			subclassClosure = new string[subclassSpan];
			subclassClosure[subclassSpan - 1] = EntityName;
			if (persistentClass.IsPolymorphic)
			{
				subclassesByDiscriminatorValue[discriminatorValue] = EntityName;
				discriminatorValues = new string[subclassSpan];
				discriminatorValues[subclassSpan - 1] = discriminatorSQLString;
				notNullColumnTableNumbers = new int[subclassSpan];
				int id =
					GetTableId(
						persistentClass.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName,
															   factory.Settings.DefaultSchemaName), subclassTableNameClosure);
				notNullColumnTableNumbers[subclassSpan - 1] = id;
				notNullColumnNames = new string[subclassSpan];
				notNullColumnNames[subclassSpan - 1] = subclassTableKeyColumnClosure[id][0]; 
				//( (Column) model.getTable().getPrimaryKey().getColumnIterator().next() ).getName();
			}
			else
			{
				discriminatorValues = null;
				notNullColumnTableNumbers = null;
				notNullColumnNames = null;
			}

			int k2 = 0;
			foreach (Subclass sc in persistentClass.SubclassIterator)
			{
				subclassClosure[k2] = sc.EntityName;
				try
				{
					if (persistentClass.IsPolymorphic)
					{
						// we now use subclass ids that are consistent across all
						// persisters for a class hierarchy, so that the use of 
						// "foo.class = Bar" works in HQL
						int subclassId = sc.SubclassId; //new Integer(k+1);
						subclassesByDiscriminatorValue[subclassId] = sc.EntityName;
						discriminatorValues[k2] = subclassId.ToString();
						int id =
							GetTableId(
								sc.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName,
														  factory.Settings.DefaultSchemaName), subclassTableNameClosure);
						notNullColumnTableNumbers[k2] = id;
						notNullColumnNames[k2] = subclassTableKeyColumnClosure[id][0]; 
						//( (Column) sc.getTable().getPrimaryKey().getColumnIterator().next() ).getName();
					}
				}
				catch (Exception e)
				{
					throw new MappingException("Error parsing discriminator value", e);
				}
				k2++;				
			}

			#endregion

			InitLockers();

			InitSubclassPropertyAliasesMap(persistentClass);

			PostConstruct(mapping);
		}
        /// <summary>
        /// Constructs the NormalizedEntityPerister for the PersistentClass.
        /// </summary>
        /// <param name="persistentClass">The PersistentClass to create the EntityPersister for.</param>
        /// <param name="cache">The configured <see cref="ICacheConcurrencyStrategy" />.</param>
        /// <param name="factory">The SessionFactory that this EntityPersister will be stored in.</param>
        /// <param name="mapping">The mapping used to retrieve type information.</param>
        public JoinedSubclassEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache,
                                             ISessionFactoryImplementor factory, IMapping mapping)
            : base(persistentClass, cache, factory)
        {
            #region DISCRIMINATOR

            if (persistentClass.IsPolymorphic)
            {
                try
                {
                    discriminatorValue     = persistentClass.SubclassId;
                    discriminatorSQLString = discriminatorValue.ToString();
                }
                catch (Exception e)
                {
                    throw new MappingException("Could not format discriminator value to SQL string", e);
                }
            }
            else
            {
                discriminatorValue     = null;
                discriminatorSQLString = null;
            }

            if (OptimisticLockMode > Versioning.OptimisticLock.Version)
            {
                throw new MappingException(string.Format("optimistic-lock=all|dirty not supported for joined-subclass mappings [{0}]", EntityName));
            }

            #endregion

            #region MULTITABLES
            int idColumnSpan = IdentifierColumnSpan;

            List <string>   tables         = new List <string>();
            List <string[]> keyColumns     = new List <string[]>();
            List <bool>     cascadeDeletes = new List <bool>();
            using (var kiter = persistentClass.KeyClosureIterator.GetEnumerator())
            {
                foreach (var tab in persistentClass.TableClosureIterator)
                {
                    kiter.MoveNext();
                    var key     = kiter.Current;
                    var tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
                    tables.Add(tabname);

                    var keyCols         = new List <string>(idColumnSpan);
                    var enumerableKCols = new SafetyEnumerable <Column>(key.ColumnIterator);
                    foreach (var kcol in enumerableKCols)
                    {
                        keyCols.Add(kcol.GetQuotedName(factory.Dialect));
                    }

                    keyColumns.Add(keyCols.ToArray());
                    cascadeDeletes.Add(key.IsCascadeDeleteEnabled && factory.Dialect.SupportsCascadeDelete);
                }
            }
            naturalOrderTableNames           = tables.ToArray();
            naturalOrderTableKeyColumns      = keyColumns.ToArray();
            naturalOrderCascadeDeleteEnabled = cascadeDeletes.ToArray();

            List <string> subtables   = new List <string>();
            List <bool>   isConcretes = new List <bool>();
            keyColumns = new List <string[]>();
            foreach (Table tab in persistentClass.SubclassTableClosureIterator)
            {
                isConcretes.Add(persistentClass.IsClassOrSuperclassTable(tab));
                string tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
                subtables.Add(tabname);
                List <string> key = new List <string>(idColumnSpan);
                foreach (Column column in tab.PrimaryKey.ColumnIterator)
                {
                    key.Add(column.GetQuotedName(factory.Dialect));
                }

                keyColumns.Add(key.ToArray());
            }
            subclassTableNameClosure      = subtables.ToArray();
            subclassTableKeyColumnClosure = keyColumns.ToArray();
            isClassOrSuperclassTable      = isConcretes.ToArray();

            constraintOrderedTableNames     = new string[subclassTableNameClosure.Length];
            constraintOrderedKeyColumnNames = new string[subclassTableNameClosure.Length][];
            int currentPosition = 0;
            for (int i = subclassTableNameClosure.Length - 1; i >= 0; i--, currentPosition++)
            {
                constraintOrderedTableNames[currentPosition]     = subclassTableNameClosure[i];
                constraintOrderedKeyColumnNames[currentPosition] = subclassTableKeyColumnClosure[i];
            }

            tableSpan       = naturalOrderTableNames.Length;
            tableNames      = Reverse(naturalOrderTableNames);
            tableKeyColumns = Reverse(naturalOrderTableKeyColumns);
            Reverse(subclassTableNameClosure, tableSpan);
            Reverse(subclassTableKeyColumnClosure, tableSpan);

            spaces = ArrayHelper.Join(tableNames, persistentClass.SynchronizedTables.ToArray());

            // Custom sql
            customSQLInsert         = new SqlString[tableSpan];
            customSQLUpdate         = new SqlString[tableSpan];
            customSQLDelete         = new SqlString[tableSpan];
            insertCallable          = new bool[tableSpan];
            updateCallable          = new bool[tableSpan];
            deleteCallable          = new bool[tableSpan];
            insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];
            updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];
            deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];

            PersistentClass pc = persistentClass;
            int             jk = tableSpan - 1;
            while (pc != null)
            {
                customSQLInsert[jk]         = pc.CustomSQLInsert;
                insertCallable[jk]          = customSQLInsert[jk] != null && pc.IsCustomInsertCallable;
                insertResultCheckStyles[jk] = pc.CustomSQLInsertCheckStyle
                                              ??
                                              ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[jk], insertCallable[jk]);
                customSQLUpdate[jk]         = pc.CustomSQLUpdate;
                updateCallable[jk]          = customSQLUpdate[jk] != null && pc.IsCustomUpdateCallable;
                updateResultCheckStyles[jk] = pc.CustomSQLUpdateCheckStyle
                                              ??
                                              ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[jk], updateCallable[jk]);
                customSQLDelete[jk]         = pc.CustomSQLDelete;
                deleteCallable[jk]          = customSQLDelete[jk] != null && pc.IsCustomDeleteCallable;
                deleteResultCheckStyles[jk] = pc.CustomSQLDeleteCheckStyle
                                              ??
                                              ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[jk], deleteCallable[jk]);
                jk--;
                pc = pc.Superclass;
            }
            if (jk != -1)
            {
                throw new AssertionFailure("Tablespan does not match height of joined-subclass hierarchy.");
            }

            #endregion

            #region PROPERTIES

            int hydrateSpan = PropertySpan;
            naturalOrderPropertyTableNumbers = new int[hydrateSpan];
            propertyTableNumbers             = new int[hydrateSpan];
            int i2 = 0;
            foreach (Property prop in persistentClass.PropertyClosureIterator)
            {
                string tabname = prop.Value.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
                propertyTableNumbers[i2]             = GetTableId(tabname, tableNames);
                naturalOrderPropertyTableNumbers[i2] = GetTableId(tabname, naturalOrderTableNames);
                i2++;
            }

            // subclass closure properties
            List <int> columnTableNumbers  = new List <int>();
            List <int> formulaTableNumbers = new List <int>();
            List <int> propTableNumbers    = new List <int>();
            foreach (Property prop in persistentClass.SubclassPropertyClosureIterator)
            {
                Table  tab     = prop.Value.Table;
                string tabname = tab.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
                int    tabnum  = GetTableId(tabname, subclassTableNameClosure);
                propTableNumbers.Add(tabnum);

                foreach (ISelectable thing in prop.ColumnIterator)
                {
                    if (thing.IsFormula)
                    {
                        formulaTableNumbers.Add(tabnum);
                    }
                    else
                    {
                        columnTableNumbers.Add(tabnum);
                    }
                }
            }

            subclassColumnTableNumberClosure   = columnTableNumbers.ToArray();
            subclassPropertyTableNumberClosure = propTableNumbers.ToArray();
            subclassFormulaTableNumberClosure  = formulaTableNumbers.ToArray();
            #endregion

            #region SUBCLASSES

            int subclassSpan = persistentClass.SubclassSpan + 1;
            subclassClosure = new string[subclassSpan];
            subclassClosure[subclassSpan - 1] = EntityName;
            if (persistentClass.IsPolymorphic)
            {
                subclassesByDiscriminatorValue[discriminatorValue] = EntityName;
                discriminatorValues = new string[subclassSpan];
                discriminatorValues[subclassSpan - 1] = discriminatorSQLString;
                notNullColumnTableNumbers             = new int[subclassSpan];
                int id =
                    GetTableId(
                        persistentClass.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName,
                                                               factory.Settings.DefaultSchemaName), subclassTableNameClosure);
                notNullColumnTableNumbers[subclassSpan - 1] = id;
                notNullColumnNames = new string[subclassSpan];
                notNullColumnNames[subclassSpan - 1] = subclassTableKeyColumnClosure[id][0];
                //( (Column) model.getTable().getPrimaryKey().getColumnIterator().next() ).getName();
            }
            else
            {
                discriminatorValues       = null;
                notNullColumnTableNumbers = null;
                notNullColumnNames        = null;
            }

            int k2 = 0;
            foreach (Subclass sc in persistentClass.SubclassIterator)
            {
                subclassClosure[k2] = sc.EntityName;
                try
                {
                    if (persistentClass.IsPolymorphic)
                    {
                        // we now use subclass ids that are consistent across all
                        // persisters for a class hierarchy, so that the use of
                        // "foo.class = Bar" works in HQL
                        int subclassId = sc.SubclassId;                         //new Integer(k+1);
                        subclassesByDiscriminatorValue[subclassId] = sc.EntityName;
                        discriminatorValues[k2] = subclassId.ToString();
                        int id =
                            GetTableId(
                                sc.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName,
                                                          factory.Settings.DefaultSchemaName), subclassTableNameClosure);
                        notNullColumnTableNumbers[k2] = id;
                        notNullColumnNames[k2]        = subclassTableKeyColumnClosure[id][0];
                        //( (Column) sc.getTable().getPrimaryKey().getColumnIterator().next() ).getName();
                    }
                }
                catch (Exception e)
                {
                    throw new MappingException("Error parsing discriminator value", e);
                }
                k2++;
            }

            #endregion

            InitLockers();

            InitSubclassPropertyAliasesMap(persistentClass);

            PostConstruct(mapping);
        }
        public SingleTableEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache,
                                          ISessionFactoryImplementor factory, IMapping mapping)
            : base(persistentClass, cache, factory)
        {
            #region CLASS + TABLE

            joinSpan            = persistentClass.JoinClosureSpan + 1;
            qualifiedTableNames = new string[joinSpan];
            isInverseTable      = new bool[joinSpan];
            isNullableTable     = new bool[joinSpan];
            keyColumnNames      = new string[joinSpan][];
            Table table = persistentClass.RootTable;
            qualifiedTableNames[0] =
                table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
            isInverseTable[0]    = false;
            isNullableTable[0]   = false;
            keyColumnNames[0]    = IdentifierColumnNames;
            cascadeDeleteEnabled = new bool[joinSpan];

            // Custom sql
            customSQLInsert         = new SqlString[joinSpan];
            customSQLUpdate         = new SqlString[joinSpan];
            customSQLDelete         = new SqlString[joinSpan];
            insertCallable          = new bool[joinSpan];
            updateCallable          = new bool[joinSpan];
            deleteCallable          = new bool[joinSpan];
            insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];
            updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];
            deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];

            customSQLInsert[0]         = persistentClass.CustomSQLInsert;
            insertCallable[0]          = customSQLInsert[0] != null && persistentClass.IsCustomInsertCallable;
            insertResultCheckStyles[0] = persistentClass.CustomSQLInsertCheckStyle
                                         ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[0], insertCallable[0]);
            customSQLUpdate[0]         = persistentClass.CustomSQLUpdate;
            updateCallable[0]          = customSQLUpdate[0] != null && persistentClass.IsCustomUpdateCallable;
            updateResultCheckStyles[0] = persistentClass.CustomSQLUpdateCheckStyle
                                         ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[0], updateCallable[0]);
            customSQLDelete[0]         = persistentClass.CustomSQLDelete;
            deleteCallable[0]          = customSQLDelete[0] != null && persistentClass.IsCustomDeleteCallable;
            deleteResultCheckStyles[0] = persistentClass.CustomSQLDeleteCheckStyle
                                         ?? ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[0], deleteCallable[0]);

            #endregion

            #region JOINS
            int j = 1;
            foreach (Join join in persistentClass.JoinClosureIterator)
            {
                qualifiedTableNames[j]  = join.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName);
                isInverseTable[j]       = join.IsInverse;
                isNullableTable[j]      = join.IsOptional;
                cascadeDeleteEnabled[j] = join.Key.IsCascadeDeleteEnabled && factory.Dialect.SupportsCascadeDelete;

                customSQLInsert[j]         = join.CustomSQLInsert;
                insertCallable[j]          = customSQLInsert[j] != null && join.IsCustomInsertCallable;
                insertResultCheckStyles[j] = join.CustomSQLInsertCheckStyle
                                             ??
                                             ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLInsert[j], insertCallable[j]);
                customSQLUpdate[j]         = join.CustomSQLUpdate;
                updateCallable[j]          = customSQLUpdate[j] != null && join.IsCustomUpdateCallable;
                updateResultCheckStyles[j] = join.CustomSQLUpdateCheckStyle
                                             ??
                                             ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLUpdate[j], updateCallable[j]);
                customSQLDelete[j]         = join.CustomSQLDelete;
                deleteCallable[j]          = customSQLDelete[j] != null && join.IsCustomDeleteCallable;
                deleteResultCheckStyles[j] = join.CustomSQLDeleteCheckStyle
                                             ??
                                             ExecuteUpdateResultCheckStyle.DetermineDefault(customSQLDelete[j], deleteCallable[j]);

                IEnumerable <Column> enumerableKeyCol = new SafetyEnumerable <Column>(join.Key.ColumnIterator);
                List <string>        kcName           = new List <string>(join.Key.ColumnSpan);
                foreach (Column col in enumerableKeyCol)
                {
                    kcName.Add(col.GetQuotedName(factory.Dialect));
                }

                keyColumnNames[j] = kcName.ToArray();

                j++;
            }

            constraintOrderedTableNames     = new string[qualifiedTableNames.Length];
            constraintOrderedKeyColumnNames = new string[qualifiedTableNames.Length][];
            for (int i = qualifiedTableNames.Length - 1, position = 0; i >= 0; i--, position++)
            {
                constraintOrderedTableNames[position]     = qualifiedTableNames[i];
                constraintOrderedKeyColumnNames[position] = keyColumnNames[i];
            }

            spaces = ArrayHelper.Join(qualifiedTableNames, ArrayHelper.ToStringArray(persistentClass.SynchronizedTables));

            bool lazyAvailable = IsInstrumented(EntityMode.Poco);

            bool            hasDeferred    = false;
            List <string>   subclassTables = new List <string>();
            List <string[]> joinKeyColumns = new List <string[]>();
            List <bool>     isConcretes    = new List <bool>();
            List <bool>     isDeferreds    = new List <bool>();
            List <bool>     isInverses     = new List <bool>();
            List <bool>     isNullables    = new List <bool>();
            List <bool>     isLazies       = new List <bool>();
            subclassTables.Add(qualifiedTableNames[0]);
            joinKeyColumns.Add(IdentifierColumnNames);
            isConcretes.Add(true);
            isDeferreds.Add(false);
            isInverses.Add(false);
            isNullables.Add(false);
            isLazies.Add(false);
            foreach (Join join in persistentClass.SubclassJoinClosureIterator)
            {
                isConcretes.Add(persistentClass.IsClassOrSuperclassJoin(join));
                isDeferreds.Add(join.IsSequentialSelect);
                isInverses.Add(join.IsInverse);
                isNullables.Add(join.IsOptional);
                isLazies.Add(lazyAvailable && join.IsLazy);
                if (join.IsSequentialSelect && !persistentClass.IsClassOrSuperclassJoin(join))
                {
                    hasDeferred = true;
                }
                subclassTables.Add(join.Table.GetQualifiedName(factory.Dialect, factory.Settings.DefaultCatalogName, factory.Settings.DefaultSchemaName));
                IEnumerable <Column> enumerableKeyCol = new SafetyEnumerable <Column>(join.Key.ColumnIterator);
                List <string>        keyCols          = new List <string>(join.Key.ColumnSpan);
                foreach (Column col in enumerableKeyCol)
                {
                    keyCols.Add(col.GetQuotedName(factory.Dialect));
                }

                joinKeyColumns.Add(keyCols.ToArray());
            }

            subclassTableSequentialSelect = isDeferreds.ToArray();
            subclassTableNameClosure      = subclassTables.ToArray();
            subclassTableIsLazyClosure    = isLazies.ToArray();
            subclassTableKeyColumnClosure = joinKeyColumns.ToArray();
            isClassOrSuperclassTable      = isConcretes.ToArray();
            isInverseSubclassTable        = isInverses.ToArray();
            isNullableSubclassTable       = isNullables.ToArray();
            hasSequentialSelects          = hasDeferred;

            #endregion

            #region DISCRIMINATOR

            if (persistentClass.IsPolymorphic)
            {
                IValue discrimValue = persistentClass.Discriminator;
                if (discrimValue == null)
                {
                    throw new MappingException("Discriminator mapping required for single table polymorphic persistence");
                }

                forceDiscriminator = persistentClass.IsForceDiscriminator;
                IEnumerator <ISelectable> iSel = discrimValue.ColumnIterator.GetEnumerator();
                iSel.MoveNext();
                ISelectable selectable = iSel.Current;
                if (discrimValue.HasFormula)
                {
                    Formula formula = (Formula)selectable;
                    discriminatorFormula         = formula.FormulaString;
                    discriminatorFormulaTemplate = formula.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry);
                    discriminatorColumnName      = null;
                    discriminatorAlias           = Discriminator_Alias;
                }
                else
                {
                    Column column = (Column)selectable;
                    discriminatorColumnName      = column.GetQuotedName(factory.Dialect);
                    discriminatorAlias           = column.GetAlias(factory.Dialect, persistentClass.RootTable);
                    discriminatorFormula         = null;
                    discriminatorFormulaTemplate = null;
                }
                discriminatorType = persistentClass.Discriminator.Type;
                if (persistentClass.IsDiscriminatorValueNull)
                {
                    discriminatorValue      = NullDiscriminator;
                    discriminatorSQLValue   = InFragment.Null;
                    discriminatorInsertable = false;
                }
                else if (persistentClass.IsDiscriminatorValueNotNull)
                {
                    discriminatorValue      = NotNullDiscriminator;
                    discriminatorSQLValue   = InFragment.NotNull;
                    discriminatorInsertable = false;
                }
                else
                {
                    discriminatorInsertable = persistentClass.IsDiscriminatorInsertable && !discrimValue.HasFormula;
                    try
                    {
                        IDiscriminatorType dtype = (IDiscriminatorType)discriminatorType;
                        discriminatorValue    = dtype.StringToObject(persistentClass.DiscriminatorValue);
                        discriminatorSQLValue = dtype.ObjectToSQLString(discriminatorValue, factory.Dialect);
                    }
                    catch (InvalidCastException cce)
                    {
                        throw new MappingException(
                                  string.Format("Illegal discriminator type: {0} of entity {1}", discriminatorType.Name, persistentClass.EntityName), cce);
                    }
                    catch (Exception e)
                    {
                        throw new MappingException("Could not format discriminator value to SQL string of entity " + persistentClass.EntityName, e);
                    }
                }
            }
            else
            {
                forceDiscriminator           = false;
                discriminatorInsertable      = false;
                discriminatorColumnName      = null;
                discriminatorAlias           = null;
                discriminatorType            = null;
                discriminatorValue           = null;
                discriminatorSQLValue        = null;
                discriminatorFormula         = null;
                discriminatorFormulaTemplate = null;
            }

            #endregion

            #region PROPERTIES

            propertyTableNumbers = new int[PropertySpan];
            int i2 = 0;
            foreach (Property prop in persistentClass.PropertyClosureIterator)
            {
                propertyTableNumbers[i2++] = persistentClass.GetJoinNumber(prop);
            }

            List <int> columnJoinNumbers    = new List <int>();
            List <int> formulaJoinedNumbers = new List <int>();
            List <int> propertyJoinNumbers  = new List <int>();
            foreach (Property prop in persistentClass.SubclassPropertyClosureIterator)
            {
                int join = persistentClass.GetJoinNumber(prop);
                propertyJoinNumbers.Add(join);

                //propertyTableNumbersByName.put( prop.getName(), join );
                propertyTableNumbersByNameAndSubclass[prop.PersistentClass.EntityName + '.' + prop.Name] = join;
                foreach (ISelectable thing in prop.ColumnIterator)
                {
                    if (thing.IsFormula)
                    {
                        formulaJoinedNumbers.Add(join);
                    }
                    else
                    {
                        columnJoinNumbers.Add(join);
                    }
                }
            }

            subclassColumnTableNumberClosure   = columnJoinNumbers.ToArray();
            subclassFormulaTableNumberClosure  = formulaJoinedNumbers.ToArray();
            subclassPropertyTableNumberClosure = propertyJoinNumbers.ToArray();

            int subclassSpan = persistentClass.SubclassSpan + 1;
            subclassClosure    = new string[subclassSpan];
            subclassClosure[0] = EntityName;
            if (persistentClass.IsPolymorphic)
            {
                subclassesByDiscriminatorValue[discriminatorValue] = EntityName;
            }

            #endregion

            #region SUBCLASSES
            if (persistentClass.IsPolymorphic)
            {
                int k = 1;
                foreach (Subclass sc in persistentClass.SubclassIterator)
                {
                    subclassClosure[k++] = sc.EntityName;
                    if (sc.IsDiscriminatorValueNull)
                    {
                        subclassesByDiscriminatorValue[NullDiscriminator] = sc.EntityName;
                    }
                    else if (sc.IsDiscriminatorValueNotNull)
                    {
                        subclassesByDiscriminatorValue[NotNullDiscriminator] = sc.EntityName;
                    }
                    else
                    {
                        if (discriminatorType == null)
                        {
                            throw new MappingException("Not available discriminator type of entity " + persistentClass.EntityName);
                        }
                        try
                        {
                            IDiscriminatorType dtype = (IDiscriminatorType)discriminatorType;
                            subclassesByDiscriminatorValue[dtype.StringToObject(sc.DiscriminatorValue)] = sc.EntityName;
                        }
                        catch (InvalidCastException cce)
                        {
                            throw new MappingException(
                                      string.Format("Illegal discriminator type: {0} of entity {1}", discriminatorType.Name, persistentClass.EntityName), cce);
                        }
                        catch (Exception e)
                        {
                            throw new MappingException("Error parsing discriminator value of entity " + persistentClass.EntityName, e);
                        }
                    }
                }
            }

            #endregion

            InitLockers();

            InitSubclassPropertyAliasesMap(persistentClass);

            PostConstruct(mapping);
        }