// --------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // --------------------------------------------------------------------------- // --------------------------------------------------------------------- // // // --------------------------------------------------------------------- namespace Microsoft.Database.Isam { using System; using System.Collections; using System.Globalization; using Microsoft.Isam.Esent.Interop; /// /// Contains the columns defined in the table. /// public class ColumnCollection : DictionaryBase, IEnumerable { /// /// The database /// private readonly IsamDatabase database; /// /// The table name /// private readonly string tableName; /// /// The cached column definition /// private string cachedColumnDefinition = null; /// /// The column definition /// private ColumnDefinition columnDefinition = null; /// /// The column update identifier /// private long columnUpdateID = 0; /// /// Whether the collection is read-only. /// private bool readOnly = false; /// /// Initializes a new instance of the class. /// public ColumnCollection() { this.database = null; } /// /// Initializes a new instance of the class. /// /// The database. /// Name of the table. internal ColumnCollection(IsamDatabase database, string tableName) { this.database = database; this.tableName = tableName; this.readOnly = true; } /// /// Gets a value indicating whether the object has a fixed size. /// /// true if the object has a fixed size; otherwise, false. public bool IsFixedSize { get { return this.readOnly; } } /// /// Gets a value indicating whether the object is read-only. /// /// true if the object is read-only; otherwise, false. public bool IsReadOnly { get { return this.readOnly; } } /// /// Gets the names. /// /// /// The names. /// /// the names of the columns in this column collection cannot be enumerated in this manner when accessing the table definition of an existing table public ICollection Names { get { if (this.database != null) { // CONSIDER: should we provide an ICollection of our column names to avoid this wart? throw new InvalidOperationException( "the names of the columns in this column collection cannot be enumerated in this manner when accessing the table definition of an existing table"); } else { return this.Dictionary.Keys; } } } /// /// Sets a value indicating whether [read only]. /// /// /// true if [read only]; otherwise, false. /// internal bool ReadOnly { set { this.readOnly = value; } } /// /// Fetches the Column Definition for the specified column name. /// /// /// The for the specifed column name. /// /// Name of the column. /// The for the specified column name. public ColumnDefinition this[string columnName] { get { if (this.database != null) { lock (this.database.IsamSession) { if (this.cachedColumnDefinition != columnName.ToLower(CultureInfo.InvariantCulture) || this.columnUpdateID != DatabaseCommon.SchemaUpdateID) { JET_COLUMNBASE columnBase; Api.JetGetColumnInfo( this.database.IsamSession.Sesid, this.database.Dbid, this.tableName, columnName, out columnBase); this.columnDefinition = ColumnDefinition.Load(this.database, this.tableName, columnBase); this.cachedColumnDefinition = columnName.ToLower(CultureInfo.InvariantCulture); this.columnUpdateID = DatabaseCommon.SchemaUpdateID; } return this.columnDefinition; } } else { return (ColumnDefinition)this.Dictionary[columnName.ToLower(CultureInfo.InvariantCulture)]; } } } /// /// Fetches the Column Definition for the specified columnid. /// /// /// The for the specifed column identifier /// /// The columnid. /// The for the specified column identifier. public ColumnDefinition this[Columnid columnid] { get { if (this.database != null) { lock (this.database.IsamSession) { if (this.cachedColumnDefinition != columnid.Name.ToLower(CultureInfo.InvariantCulture) || this.columnUpdateID != DatabaseCommon.SchemaUpdateID) { JET_COLUMNBASE columnBase; Api.JetGetColumnInfo( this.database.IsamSession.Sesid, this.database.Dbid, this.tableName, columnid.Name, out columnBase); this.columnDefinition = ColumnDefinition.Load(this.database, this.tableName, columnBase); this.cachedColumnDefinition = columnid.Name.ToLower(CultureInfo.InvariantCulture); this.columnUpdateID = DatabaseCommon.SchemaUpdateID; } return this.columnDefinition; } } else { return (ColumnDefinition)this.Dictionary[columnid.Name.ToLower(CultureInfo.InvariantCulture)]; } } } /// /// Fetches an enumerator containing all the columns in this table. /// /// An enumerator containing all the columns in this table. /// /// This is the type safe version that may not work in other CLR /// languages. /// public new ColumnEnumerator GetEnumerator() { if (this.database != null) { return new ColumnEnumerator(this.database, this.tableName); } else { return new ColumnEnumerator(Dictionary.GetEnumerator()); } } /// /// Adds the specified column definition. /// /// The column definition. public void Add(ColumnDefinition columnDefinition) { Dictionary.Add(columnDefinition.Name.ToLower(CultureInfo.InvariantCulture), columnDefinition); } /// /// Determines if the table contains a column with the given name /// /// Name of the column. /// Whether the specified column exists in the collection. public bool Contains(string columnName) { if (this.database != null) { lock (this.database.IsamSession) { bool exists = false; try { JET_COLUMNBASE columnBase; Api.JetGetColumnInfo( this.database.IsamSession.Sesid, this.database.Dbid, this.tableName, columnName, out columnBase); exists = true; } catch (EsentColumnNotFoundException) { } return exists; } } else { return Dictionary.Contains(columnName.ToLower(CultureInfo.InvariantCulture)); } } /// /// Determines if the table contains a column with the given columnid /// /// The columnid. /// Whether the specified column exists in the collection. public bool Contains(Columnid columnid) { if (this.database != null) { lock (this.database.IsamSession) { bool exists = false; try { JET_COLUMNBASE columnBase; Api.JetGetColumnInfo( this.database.IsamSession.Sesid, this.database.Dbid, this.tableName, columnid.Name, out columnBase); exists = true; } catch (EsentColumnNotFoundException) { } return exists; } } else { return Dictionary.Contains(columnid.Name.ToLower(CultureInfo.InvariantCulture)); } } /// /// Removes the specified column name. /// /// Name of the column. public void Remove(string columnName) { Dictionary.Remove(columnName.ToLower(CultureInfo.InvariantCulture)); } /// /// Removes the specified columnid. /// /// The columnid. public void Remove(Columnid columnid) { Dictionary.Remove(columnid.Name.ToLower(CultureInfo.InvariantCulture)); } /// /// Fetches an enumerator containing all the columns in this table /// /// /// An object that can be used to iterate through the collection. /// /// /// This is the standard version that will work with other CLR /// languages. /// IEnumerator IEnumerable.GetEnumerator() { return (IEnumerator)this.GetEnumerator(); } /// /// Performs additional custom processes before clearing the contents of the instance. /// protected override void OnClear() { this.CheckReadOnly(); } /// /// Performs additional custom processes before inserting a new element into the instance. /// /// The key of the element to insert. /// The value of the element to insert. protected override void OnInsert(object key, object value) { this.CheckReadOnly(); } /// /// Performs additional custom processes before removing an element from the instance. /// /// The key of the element to remove. /// The value of the element to remove. protected override void OnRemove(object key, object value) { this.CheckReadOnly(); } /// /// Performs additional custom processes before setting a value in the instance. /// /// The key of the element to locate. /// The old value of the element associated with . /// The new value of the element associated with . protected override void OnSet(object key, object oldValue, object newValue) { this.CheckReadOnly(); } /// /// Performs additional custom processes when validating the element with the specified key and value. /// /// The key of the element to validate. /// The value of the element to validate. /// /// key must be of type System.String;key /// or /// value must be of type ColumnDefinition;value /// or /// key must match value.Name;key /// protected override void OnValidate(object key, object value) { if (!(key is string)) { throw new ArgumentException("key must be of type System.String", "key"); } if (!(value is ColumnDefinition)) { throw new ArgumentException("value must be of type ColumnDefinition", "value"); } if (((string)key).ToLower(CultureInfo.InvariantCulture) != ((ColumnDefinition)value).Name.ToLower(CultureInfo.InvariantCulture)) { throw new ArgumentException("key must match value.Name", "key"); } } /// /// Checks the read only. /// /// this index collection cannot be changed private void CheckReadOnly() { if (this.readOnly) { throw new NotSupportedException("this index collection cannot be changed"); } } } }