public void Type(IDiscriminatorType persistentType) { Type(persistentType.GetType()); }
//INITIALIZATION: /// <summary> /// Constructs the NormalizedEntityPerister for the PersistentClass. /// </summary> /// <param name="model">The PeristentClass to create the EntityPersister for.</param> /// <param name="factory">The SessionFactory that this EntityPersister will be stored in.</param> public NormalizedEntityPersister( PersistentClass model, ISessionFactoryImplementor factory ) : base( model, factory ) { // I am am making heavy use of the "this." just to help me with debugging what is a local variable to the // constructor versus what is an class scoped variable. I am only doing this when we are using fields // instead of properties because it is easy to tell properties by the Case. // CLASS + TABLE this.factory = factory; Table table = model.RootTable; this.qualifiedTableName = table.GetQualifiedName( Dialect, factory.DefaultSchema ); // DISCRIMINATOR object discriminatorValue; if( model.IsPolymorphic ) { // when we have a Polymorphic model then we are going to add a column "clazz_" to // the sql statement that will be a large CASE statement where we will use the // integer value to tell us which class to instantiate for the record. this.discriminatorColumnName = "clazz_"; try { this.discriminatorType = ( IDiscriminatorType ) NHibernateUtil.Int32; discriminatorValue = 0; this.discriminatorSQLString = "0"; } catch( Exception e ) { throw new MappingException( "Could not format discriminator value '0' to sql string using the IType NHibernate.Types.Int32Type", e ); } } else { this.discriminatorColumnName = null; this.discriminatorType = null; discriminatorValue = null; this.discriminatorSQLString = null; } if( OptimisticLockMode != OptimisticLockMode.Version ) { throw new MappingException( "optimistic-lock attribute not supported for joined-subclass mappings: " + ClassName ); } //MULTITABLES // these two will later be converted into arrays for the fields tableNames and tableKeyColumns ArrayList tables = new ArrayList(); ArrayList keyColumns = new ArrayList(); tables.Add( this.qualifiedTableName ); keyColumns.Add( base.IdentifierColumnNames ); // move through each table that contains the data for this entity. foreach( Table tab in model.TableClosureCollection ) { string tabname = tab.GetQualifiedName( Dialect, factory.DefaultSchema ); if( !tabname.Equals( qualifiedTableName ) ) { tables.Add( tabname ); string[ ] key = new string[tab.PrimaryKey.ColumnCollection.Count]; int k = 0; foreach( Column col in tab.PrimaryKey.ColumnCollection ) { key[ k++ ] = col.GetQuotedName( Dialect ); } keyColumns.Add( key ); } } this.naturalOrderTableNames = ( string[ ] ) tables.ToArray( typeof( string ) ); this.naturalOrderTableKeyColumns = ( string[ ][ ] ) keyColumns.ToArray( typeof( string[ ] ) ); // the description of these variables is the same as before ArrayList subtables = new ArrayList(); keyColumns = new ArrayList(); subtables.Add( this.qualifiedTableName ); keyColumns.Add( base.IdentifierColumnNames ); foreach( Table tab in model.SubclassTableClosureCollection ) { string tabname = tab.GetQualifiedName( Dialect, factory.DefaultSchema ); if( !tabname.Equals( qualifiedTableName ) ) { subtables.Add( tabname ); string[ ] key = new string[tab.PrimaryKey.ColumnCollection.Count]; int k = 0; foreach( Column col in tab.PrimaryKey.ColumnCollection ) { key[ k++ ] = col.GetQuotedName( Dialect ); } keyColumns.Add( key ); } } // convert the local ArrayList variables into arrays for the fields in the class this.subclassTableNameClosure = ( string[ ] ) subtables.ToArray( typeof( string ) ); this.subclassTableKeyColumns = ( string[ ][ ] ) keyColumns.ToArray( typeof( string[ ] ) ); this.isClassOrSuperclassTable = new bool[this.subclassTableNameClosure.Length]; for( int j = 0; j < subclassTableNameClosure.Length; j++ ) { this.isClassOrSuperclassTable[ j ] = tables.Contains( this.subclassTableNameClosure[ j ] ); } int len = naturalOrderTableNames.Length; tableNames = Reverse( naturalOrderTableNames ); tableKeyColumns = Reverse( naturalOrderTableKeyColumns ); Array.Reverse( subclassTableNameClosure, 0, len ); Array.Reverse( subclassTableKeyColumns, 0, len ); // PROPERTIES // initialize the lengths of all of the Property related fields in the class this.propertyTables = new int[HydrateSpan]; this.naturalOrderPropertyTables = new int[HydrateSpan]; this.propertyColumnNames = new string[HydrateSpan][ ]; this.propertyColumnNameAliases = new string[HydrateSpan][ ]; this.propertyColumnSpans = new int[HydrateSpan]; this.propertyFormulaTemplates = new string[ HydrateSpan ]; HashedSet thisClassProperties = new HashedSet(); int i = 0; bool foundFormula = false; foreach( Mapping.Property prop in model.PropertyClosureCollection ) { thisClassProperties.Add( prop ); Table tab = prop.Value.Table; string tabname = tab.GetQualifiedName( Dialect, factory.DefaultSchema ); this.propertyTables[ i ] = GetTableId( tabname, this.tableNames ); this.naturalOrderPropertyTables[ i ] = GetTableId( tabname, this.naturalOrderTableNames ); if ( prop.IsFormula ) { this.propertyColumnNameAliases[ i ] = new string[] { prop.Formula.Alias }; this.propertyColumnSpans[ i ] = 1; this.propertyFormulaTemplates[ i ] = prop.Formula.GetTemplate( Dialect ); foundFormula = true; } else { this.propertyColumnSpans[ i ] = prop.ColumnSpan; string[ ] propCols = new string[propertyColumnSpans[ i ]]; string[ ] propAliases = new string[propertyColumnSpans[ i ]]; int j = 0; foreach( Column col in prop.ColumnCollection ) { string colname = col.GetQuotedName( Dialect ); propCols[ j ] = colname; propAliases[ j ] = col.Alias( Dialect, tab.UniqueInteger.ToString() + StringHelper.Underscore ); j++; } this.propertyColumnNames[ i ] = propCols; this.propertyColumnNameAliases[ i ] = propAliases; } i++; } this.hasFormulaProperties = foundFormula; // check distinctness of columns for this specific subclass only HashedSet distinctColumns = new HashedSet(); CheckColumnDuplication( distinctColumns, model.Key.ColumnCollection ); foreach( Mapping.Property prop in model.PropertyCollection ) { if( prop.IsUpdateable || prop.IsInsertable ) { CheckColumnDuplication( distinctColumns, prop.ColumnCollection ); } } // subclass closure properties ArrayList columns = new ArrayList(); //this.subclassColumnClosure ArrayList aliases = new ArrayList(); ArrayList formulaAliases = new ArrayList(); ArrayList formulaTemplates = new ArrayList(); ArrayList types = new ArrayList(); //this.subclassPropertyTypeClosure ArrayList names = new ArrayList(); //this.subclassPropertyNameClosure ArrayList propColumns = new ArrayList(); //this.subclassPropertyColumnNameClosure ArrayList coltables = new ArrayList(); //this.subclassColumnTableNumberClosure ArrayList formtables = new ArrayList(); ArrayList joinedFetchesList = new ArrayList(); //this.subclassPropertyEnableJoinedFetch ArrayList propTables = new ArrayList(); // this.subclassPropertyTableNameClosure ArrayList definedBySubclass = new ArrayList(); // this.propertyDefinedOnSubclass foreach( Mapping.Property prop in model.SubclassPropertyClosureCollection ) { names.Add( prop.Name ); definedBySubclass.Add( !thisClassProperties.Contains( prop ) ); Table tab = prop.Value.Table; string tabname = tab.GetQualifiedName( Dialect, factory.DefaultSchema ); int tabnum = GetTableId( tabname, subclassTableNameClosure ); propTables.Add( tabnum ); types.Add( prop.Type ); if ( prop.IsFormula ) { formulaTemplates.Add( prop.Formula.GetTemplate( Dialect ) ); propColumns.Add( new string [] { } ) ; formulaAliases.Add( prop.Formula.Alias ); formtables.Add( tabnum ); } else { string[ ] cols = new string[prop.ColumnSpan]; int l = 0; foreach( Column col in prop.ColumnCollection ) { columns.Add( col.GetQuotedName( Dialect ) ); coltables.Add( tabnum ); cols[ l++ ] = col.GetQuotedName( Dialect ); aliases.Add( col.Alias( Dialect, tab.UniqueInteger.ToString() + StringHelper.Underscore ) ); } propColumns.Add( cols ); } joinedFetchesList.Add( prop.Value.OuterJoinFetchSetting ); } subclassColumnClosure = ( string[ ] ) columns.ToArray( typeof( string ) ); subclassColumnClosureAliases = ( string[ ] ) aliases.ToArray( typeof( string ) ); subclassColumnTableNumberClosure = ( int[ ] ) coltables.ToArray( typeof( int ) ); subclassPropertyTypeClosure = ( IType[ ] ) types.ToArray( typeof( IType ) ); subclassPropertyNameClosure = ( string[ ] ) names.ToArray( typeof( string ) ); subclassPropertyTableNumberClosure = ( int[ ] ) propTables.ToArray( typeof( int ) ); subclassFormulaAliasClosure = ( string[ ] ) formulaAliases.ToArray( typeof( string ) ); subclassFormulaTemplateClosure = ( string[ ] ) formulaTemplates.ToArray( typeof( string ) ); subclassFormulaTableNumberClosure = ( int[ ] ) formtables.ToArray( typeof( int ) ); subclassPropertyColumnNameClosure = ( string[ ][ ] ) propColumns.ToArray( typeof( string[ ] ) ); subclassPropertyEnableJoinedFetch = new OuterJoinFetchStrategy[ joinedFetchesList.Count ]; int n = 0; foreach( OuterJoinFetchStrategy ojlType in joinedFetchesList ) { subclassPropertyEnableJoinedFetch[ n++ ] = ojlType; } propertyDefinedOnSubclass = new bool[ definedBySubclass.Count ]; n = 0; foreach( bool pdos in definedBySubclass ) { propertyDefinedOnSubclass[ n++ ] = pdos; } // ****** Moved the sql generation to PostIntantiate ***** System.Type mappedClass = model.MappedClass; // SUBCLASSES // all of the classes spanned, so even though there might be 2 subclasses we need to // add in the baseclass - so we add 1 to the Closure int subclassSpan = model.SubclassSpan + 1; this.subclassClosure = new System.Type[subclassSpan]; // start with the mapped class as the last element in the subclassClosure this.subclassClosure[ subclassSpan - 1 ] = mappedClass; if( model.IsPolymorphic ) { this.subclassesByDiscriminatorValue.Add( discriminatorValue, mappedClass ); this.discriminatorValues = new string[subclassSpan]; this.discriminatorValues[ subclassSpan - 1 ] = discriminatorSQLString; this.tableNumbers = new int[subclassSpan]; int id = GetTableId( model.Table.GetQualifiedName( Dialect, factory.DefaultSchema ), this.subclassTableNameClosure ); this.tableNumbers[ subclassSpan - 1 ] = id; this.notNullColumns = new string[subclassSpan]; this.notNullColumns[ subclassSpan - 1 ] = subclassTableKeyColumns[ id ][ 0 ]; /* foreach( Column col in model.Table.PrimaryKey.ColumnCollection ) { notNullColumns[ subclassSpan - 1 ] = col.GetQuotedName( Dialect ); //only once } */ } else { discriminatorValues = null; tableNumbers = null; notNullColumns = null; } int p = 0; foreach( Subclass sc in model.SubclassCollection ) { subclassClosure[ p ] = sc.MappedClass; try { if( model.IsPolymorphic ) { int disc = p + 1; subclassesByDiscriminatorValue.Add( disc, sc.MappedClass ); discriminatorValues[ p ] = disc.ToString(); int id = GetTableId( sc.Table.GetQualifiedName( Dialect, factory.DefaultSchema ), this.subclassTableNameClosure ); tableNumbers[ p ] = id; notNullColumns[ p ] = subclassTableKeyColumns[ id ][ 0 ]; /* foreach( Column col in sc.Table.PrimaryKey.ColumnCollection ) { notNullColumns[ p ] = col.GetQuotedName( Dialect ); //only once; } */ } } catch( Exception e ) { throw new MappingException( "Error parsing discriminator value", e ); } p++; } // moved the propertyHasColumns into PostInstantiate as it needs the SQL strings // needs identifier info so moved to PostInstatiate //InitLockers( ); InitSubclassPropertyAliasesMap( model ); }
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); }
//INITIALIZATION: public EntityPersister(PersistentClass model, ISessionFactoryImplementor factory) : base(model, factory) { // CLASS + TABLE System.Type mappedClass = model.MappedClass; this.factory = factory; Table table = model.RootTable; qualifiedTableName = table.GetQualifiedName(Dialect, factory.DefaultSchema); tableNames = new string[] { qualifiedTableName }; // detect mapping errors HashedSet distinctColumns = new HashedSet(); // DISCRIMINATOR object discriminatorValue; if (model.IsPolymorphic) { IValue d = model.Discriminator; if (d == null) { throw new MappingException("discriminator mapping required for polymorphic persistence"); } forceDiscriminator = model.IsForceDiscriminator; // the discriminator will have only one column foreach (Column discColumn in d.ColumnCollection) { discriminatorColumnName = discColumn.GetQuotedName(Dialect); discriminatorAlias = discColumn.Alias(Dialect); } discriminatorType = model.Discriminator.Type; if (model.IsDiscriminatorValueNull) { discriminatorValue = NullDiscriminator; discriminatorSQLValue = InFragment.Null; discriminatorInsertable = false; } else if (model.IsDiscriminatorValueNotNull) { discriminatorValue = NotNullDiscriminator; discriminatorSQLValue = InFragment.NotNull; discriminatorInsertable = false; } else { discriminatorInsertable = model.IsDiscriminatorInsertable; try { IDiscriminatorType dtype = ( IDiscriminatorType )discriminatorType; discriminatorValue = dtype.StringToObject(model.DiscriminatorValue); discriminatorSQLValue = dtype.ObjectToSQLString(discriminatorValue); } catch (InvalidCastException) { throw new MappingException(string.Format("Illegal discriminator type: {0}", discriminatorType.Name)); } catch (Exception e) { string msg = String.Format("Could not format discriminator value '{0}' to sql string using the IType {1}", model.DiscriminatorValue, model.Discriminator.Type.ToString()); throw new MappingException(msg, e); } if (discriminatorInsertable) { distinctColumns.Add(discriminatorColumnName); } } } else { forceDiscriminator = false; discriminatorInsertable = false; discriminatorColumnName = null; discriminatorAlias = null; discriminatorType = null; discriminatorValue = null; discriminatorSQLValue = null; } // PROPERTIES CheckColumnDuplication(distinctColumns, model.Key.ColumnCollection); propertyColumnNames = new string[HydrateSpan][]; propertyColumnAliases = new string[HydrateSpan][]; propertyColumnSpans = new int[HydrateSpan]; propertyFormulaTemplates = new string[HydrateSpan]; ArrayList thisClassProperties = new ArrayList(); int i = 0; bool foundColumn = false; bool foundFormula = false; foreach (Mapping.Property prop in model.PropertyClosureCollection) { thisClassProperties.Add(prop); if (prop.IsFormula) { propertyColumnAliases[i] = new string[] { prop.Formula.Alias }; propertyColumnSpans[i] = 1; propertyFormulaTemplates[i] = prop.Formula.GetTemplate(Dialect); foundFormula = true; } else { int span = prop.ColumnSpan; propertyColumnSpans[i] = span; string[] colNames = new string[span]; string[] colAliases = new string[span]; int j = 0; foreach (Column col in prop.ColumnCollection) { colAliases[j] = col.Alias(Dialect); colNames[j] = col.GetQuotedName(Dialect); j++; if (prop.IsUpdateable) { foundColumn = true; } } propertyColumnNames[i] = colNames; propertyColumnAliases[i] = colAliases; } i++; // columns must be unique across all subclasses if (prop.IsUpdateable || prop.IsInsertable) { CheckColumnDuplication(distinctColumns, prop.ColumnCollection); } } hasFormulaProperties = foundFormula; hasUpdateableColumns = foundColumn; ArrayList columns = new ArrayList(); ArrayList aliases = new ArrayList(); ArrayList formulas = new ArrayList(); ArrayList formulaAliases = new ArrayList(); ArrayList formulaTemplates = new ArrayList(); ArrayList types = new ArrayList(); ArrayList names = new ArrayList(); ArrayList propColumns = new ArrayList(); ArrayList joinedFetchesList = new ArrayList(); ArrayList definedBySubclass = new ArrayList(); foreach (Mapping.Property prop in model.SubclassPropertyClosureCollection) { names.Add(prop.Name); definedBySubclass.Add(!thisClassProperties.Contains(prop)); types.Add(prop.Type); if (prop.IsFormula) { formulas.Add(prop.Formula.FormulaString); formulaTemplates.Add(prop.Formula.GetTemplate(Dialect)); propColumns.Add(new string[0]); formulaAliases.Add(prop.Formula.Alias); } else { string[] cols = new string[prop.ColumnSpan]; int l = 0; foreach (Column col in prop.ColumnCollection) { columns.Add(col.GetQuotedName(Dialect)); aliases.Add(col.Alias(Dialect)); cols[l++] = col.GetQuotedName(Dialect); } propColumns.Add(cols); } joinedFetchesList.Add(prop.Value.OuterJoinFetchSetting); } subclassColumnClosure = ( string[] )columns.ToArray(typeof(string)); subclassFormulaClosure = ( string[] )formulas.ToArray(typeof(string)); subclassFormulaTemplateClosure = ( string[] )formulaTemplates.ToArray(typeof(string)); subclassPropertyTypeClosure = ( IType[] )types.ToArray(typeof(IType)); subclassColumnAliasClosure = ( string[] )aliases.ToArray(typeof(string)); subclassFormulaAliasClosure = ( string[] )formulaAliases.ToArray(typeof(string)); subclassPropertyNameClosure = ( string[] )names.ToArray(typeof(string)); subclassPropertyColumnNameClosure = ( string[] [] )propColumns.ToArray(typeof(string[])); subclassPropertyEnableJoinedFetch = new OuterJoinFetchStrategy[joinedFetchesList.Count]; int m = 0; foreach (OuterJoinFetchStrategy qq in joinedFetchesList) { subclassPropertyEnableJoinedFetch[m++] = qq; } propertyDefinedOnSubclass = new bool[definedBySubclass.Count]; m = 0; foreach (bool val in definedBySubclass) { propertyDefinedOnSubclass[m++] = val; } // SQL string generation moved to PostInstantiate int subclassSpan = model.SubclassSpan + 1; subclassClosure = new System.Type[subclassSpan]; subclassClosure[0] = mappedClass; if (model.IsPolymorphic) { subclassesByDiscriminatorValue.Add(discriminatorValue, mappedClass); } // SUBCLASSES if (model.IsPolymorphic) { int k = 1; foreach (Subclass sc in model.SubclassCollection) { subclassClosure[k++] = sc.MappedClass; if (sc.IsDiscriminatorValueNull) { subclassesByDiscriminatorValue.Add(NullDiscriminator, sc.MappedClass); } else if (sc.IsDiscriminatorValueNotNull) { subclassesByDiscriminatorValue.Add(NotNullDiscriminator, sc.MappedClass); } else { try { IDiscriminatorType dtype = discriminatorType as IDiscriminatorType; subclassesByDiscriminatorValue.Add( dtype.StringToObject(sc.DiscriminatorValue), sc.MappedClass); } catch (InvalidCastException) { throw new MappingException(string.Format("Illegal discriminator type: {0}", discriminatorType.Name)); } catch (Exception e) { throw new MappingException(string.Format("Error parsing discriminator value: '{0}'", sc.DiscriminatorValue), e); } } } } // This is in PostInstatiate as it needs identifier info //InitLockers(); InitSubclassPropertyAliasesMap(model); }