diff --git a/src/NHibernate/Loader/Loader.cs b/src/NHibernate/Loader/Loader.cs index ad3b5109021..3619a767a1c 100644 --- a/src/NHibernate/Loader/Loader.cs +++ b/src/NHibernate/Loader/Loader.cs @@ -82,7 +82,8 @@ public sealed class QueryCacheInfo /// /// Caches subclass entity aliases for given persister index in and subclass entity name /// - private readonly ConcurrentDictionary, string[][]> _subclassEntityAliasesMap = new ConcurrentDictionary, string[][]>(); + private readonly Lazy, string[][]>> _subclassEntityAliasesMap = + new(() => new ConcurrentDictionary, string[][]>()); protected Loader(ISessionFactoryImplementor factory) { @@ -1322,7 +1323,7 @@ private void LoadFromResultSet(DbDataReader rs, int i, object obj, ILoadable per private string[][] GetSubclassEntityAliases(int i, ILoadable persister) { var cacheKey = System.Tuple.Create(i, persister.EntityName); - return _subclassEntityAliasesMap.GetOrAdd( + return _subclassEntityAliasesMap.Value.GetOrAdd( cacheKey, k => EntityAliases[i].GetSuffixedPropertyAliases(persister)); } diff --git a/src/NHibernate/Mapping/Constraint.cs b/src/NHibernate/Mapping/Constraint.cs index 5647d4f4906..28ba203fc2b 100644 --- a/src/NHibernate/Mapping/Constraint.cs +++ b/src/NHibernate/Mapping/Constraint.cs @@ -15,7 +15,7 @@ namespace NHibernate.Mapping public abstract class Constraint : IRelationalModel { private string name; - private readonly List columns = new List(); + private readonly List columns = new List(1); private Table table; /// diff --git a/src/NHibernate/Mapping/ForeignKey.cs b/src/NHibernate/Mapping/ForeignKey.cs index 3d33a3423f7..1359b51c752 100644 --- a/src/NHibernate/Mapping/ForeignKey.cs +++ b/src/NHibernate/Mapping/ForeignKey.cs @@ -2,6 +2,7 @@ using System.Text; using NHibernate.Util; using System; +using System.Linq; namespace NHibernate.Mapping { @@ -14,7 +15,7 @@ public class ForeignKey : Constraint private Table referencedTable; private string referencedEntityName; private bool cascadeDeleteEnabled; - private readonly List referencedColumns = new List(); + private List referencedColumns; /// /// Generates the SQL string to create the named Foreign Key Constraint in the database. @@ -26,29 +27,26 @@ public class ForeignKey : Constraint /// /// A string that contains the SQL to create the named Foreign Key Constraint. /// - public override string SqlConstraintString(Dialect.Dialect d, string constraintName, string defaultCatalog, string defaultSchema) - { - string[] cols = new string[ColumnSpan]; - string[] refcols = new string[ColumnSpan]; - int i = 0; - IEnumerable refiter; - if (IsReferenceToPrimaryKey) - refiter = referencedTable.PrimaryKey.ColumnIterator; - else - refiter = referencedColumns; - foreach (Column column in ColumnIterator) - { - cols[i] = column.GetQuotedName(d); - i++; - } + public override string SqlConstraintString( + Dialect.Dialect d, + string constraintName, + string defaultCatalog, + string defaultSchema) + { + var refiter = IsReferenceToPrimaryKey + ? referencedTable.PrimaryKey.Columns + : referencedColumns; + + var cols = Columns.ToArray(column => column.GetQuotedName(d)); + var refcols = refiter.ToArray(column => column.GetQuotedName(d)); + + string result = d.GetAddForeignKeyConstraintString( + constraintName, + cols, + referencedTable.GetQualifiedName(d, defaultCatalog, defaultSchema), + refcols, + IsReferenceToPrimaryKey); - i = 0; - foreach (Column column in refiter) - { - refcols[i] = column.GetQuotedName(d); - i++; - } - string result = d.GetAddForeignKeyConstraintString(constraintName, cols, referencedTable.GetQualifiedName(d, defaultCatalog, defaultSchema), refcols, IsReferenceToPrimaryKey); return cascadeDeleteEnabled && d.SupportsCascadeDelete ? result + " on delete cascade" : result; } @@ -172,40 +170,24 @@ public virtual void AddReferencedColumns(IEnumerable referencedColumnsIt private void AddReferencedColumn(Column column) { + referencedColumns ??= new List(1); if (!referencedColumns.Contains(column)) referencedColumns.Add(column); } internal void AddReferencedTable(PersistentClass referencedClass) { - if (referencedColumns.Count > 0) - { - referencedTable = referencedColumns[0].Value.Table; - } - else - { - referencedTable = referencedClass.Table; - } + referencedTable = IsReferenceToPrimaryKey ? referencedClass.Table : referencedColumns[0].Value.Table; } public override string ToString() { - if (!IsReferenceToPrimaryKey) - { - var result = new StringBuilder(); - result.Append(GetType().FullName) - .Append('(') - .Append(Table.Name) - .Append(string.Join(", ", Columns)) - .Append(" ref-columns:") - .Append('(') - .Append(string.Join(", ", ReferencedColumns)) - .Append(") as ") - .Append(Name); - return result.ToString(); - } + if (IsReferenceToPrimaryKey) + return base.ToString(); - return base.ToString(); + var columns = string.Join(", ", Columns); + var refColumns = string.Join(", ", referencedColumns); + return $"{GetType().FullName}({Table.Name}{columns} ref-columns:({refColumns}) as {Name}"; } public bool HasPhysicalConstraint @@ -218,7 +200,11 @@ public bool HasPhysicalConstraint public IList ReferencedColumns { - get { return referencedColumns; } + get + { + referencedColumns ??= new List(1); + return referencedColumns; + } } public string ReferencedEntityName @@ -228,10 +214,7 @@ public string ReferencedEntityName } /// Does this foreignkey reference the primary key of the reference table - public bool IsReferenceToPrimaryKey - { - get { return referencedColumns.Count == 0; } - } + public bool IsReferenceToPrimaryKey => referencedColumns == null || referencedColumns.Count == 0; public string GeneratedConstraintNamePrefix => "FK_"; @@ -242,12 +225,7 @@ public override bool IsGenerated(Dialect.Dialect dialect) if (dialect.SupportsNullInUnique || IsReferenceToPrimaryKey) return true; - foreach (var column in ReferencedColumns) - { - if (column.IsNullable) - return false; - } - return true; + return referencedColumns.All(column => !column.IsNullable); } } } diff --git a/src/NHibernate/Mapping/Index.cs b/src/NHibernate/Mapping/Index.cs index a29ec92152a..7e8c17a6fd6 100644 --- a/src/NHibernate/Mapping/Index.cs +++ b/src/NHibernate/Mapping/Index.cs @@ -14,7 +14,7 @@ namespace NHibernate.Mapping public class Index : IRelationalModel { private Table table; - private readonly List columns = new List(); + private readonly List columns = new List(1); private string name; public static string BuildSqlCreateIndexString(Dialect.Dialect dialect, string name, Table table, diff --git a/src/NHibernate/Mapping/SimpleValue.cs b/src/NHibernate/Mapping/SimpleValue.cs index 0f9f9a7f084..b63e4ceb984 100644 --- a/src/NHibernate/Mapping/SimpleValue.cs +++ b/src/NHibernate/Mapping/SimpleValue.cs @@ -15,7 +15,7 @@ namespace NHibernate.Mapping [Serializable] public class SimpleValue : IKeyValue { - private readonly List columns = new List(); + private readonly List columns = new List(1); private IType type; private IDictionary typeParameters; diff --git a/src/NHibernate/Mapping/Table.cs b/src/NHibernate/Mapping/Table.cs index 5311ece174d..8c9b9d0f761 100644 --- a/src/NHibernate/Mapping/Table.cs +++ b/src/NHibernate/Mapping/Table.cs @@ -1064,9 +1064,12 @@ internal ForeignKeyKey(IEnumerable columns, string referencedClassName, { this.referencedClassName = referencedClassName; this.columns = new List(columns); + this.columns.TrimExcess(); + if (referencedColumns != null) { this.referencedColumns = new List(referencedColumns); + this.referencedColumns.TrimExcess(); } else { diff --git a/src/NHibernate/SqlCommand/SqlString.cs b/src/NHibernate/SqlCommand/SqlString.cs index b9576d0aa76..8f5a1656382 100644 --- a/src/NHibernate/SqlCommand/SqlString.cs +++ b/src/NHibernate/SqlCommand/SqlString.cs @@ -215,6 +215,9 @@ internal SqlString(IEnumerable parts) _firstPartIndex = _parts.Count > 0 ? 0 : -1; _lastPartIndex = _parts.Count - 1; _length = sqlIndex; + + _parts.TrimExcess(); + _parameters.TrimExcess(); } #endregion