// --------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // --------------------------------------------------------------------------- // --------------------------------------------------------------------- // // // --------------------------------------------------------------------- namespace Microsoft.Database.Isam { using System; using System.Collections; using System.Globalization; using Microsoft.Isam.Esent.Interop; /// /// Manages a collection of tables for a database /// public class TableCollection : DictionaryBase, IEnumerable { /// /// The database /// private readonly IsamDatabase database; /// /// The read only /// private readonly bool readOnly = false; /// /// The cached table definition /// private string cachedTableDefinition = null; /// /// The table definition /// private TableDefinition tableDefinition = null; /// /// The table update identifier /// private long tableUpdateID = 0; /// /// Initializes a new instance of the class. /// public TableCollection() { this.database = null; } /// /// Initializes a new instance of the class. /// /// The database. internal TableCollection(IsamDatabase database) { this.database = database; 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 of the tables. /// /// /// The names. /// /// the names of the tables in this table collection cannot be enumerated in this manner when accessing the table collection of a database public ICollection Names { get { if (this.database != null) { // CONSIDER: should we provide an ICollection of our table names to avoid this wart? throw new InvalidOperationException("the names of the tables in this table collection cannot be enumerated in this manner when accessing the table collection of a database"); } else { return this.Dictionary.Keys; } } } /// /// Fetches the Table Definition for the specified table name /// /// /// The . /// /// Name of the table. /// A object representing the specified table. public TableDefinition this[string tableName] { get { if (this.database != null) { lock (this.database.IsamSession) { if (this.cachedTableDefinition != tableName.ToLower(CultureInfo.InvariantCulture) || this.tableUpdateID != DatabaseCommon.SchemaUpdateID) { JET_OBJECTINFO objectInfo; Api.JetGetObjectInfo( this.database.IsamSession.Sesid, this.database.Dbid, JET_objtyp.Table, tableName, out objectInfo); this.tableDefinition = TableDefinition.Load(this.database, tableName, objectInfo); this.cachedTableDefinition = tableName.ToLower(CultureInfo.InvariantCulture); this.tableUpdateID = DatabaseCommon.SchemaUpdateID; } return this.tableDefinition; } } else { return (TableDefinition)Dictionary[tableName.ToLower(CultureInfo.InvariantCulture)]; } } set { this.Dictionary[tableName.ToLower(CultureInfo.InvariantCulture)] = value; } } /// /// Determines if the database contains a table with the given name /// /// Name of the table. /// Whether the named table exists in this database. public bool Contains(string tableName) { if (this.database != null) { lock (this.database.IsamSession) { bool exists = false; try { JET_OBJECTINFO objectInfo; Api.JetGetObjectInfo( this.database.IsamSession.Sesid, this.database.Dbid, JET_objtyp.Table, tableName, out objectInfo); exists = true; } catch (EsentObjectNotFoundException) { } return exists; } } else { return Dictionary.Contains(tableName.ToLower(CultureInfo.InvariantCulture)); } } /// /// Fetches an enumerator containing all the tables in this database. /// /// An enumerator containing all the tables in this database. /// /// This is the type safe version that may not work in other CLR /// languages. /// public new TableEnumerator GetEnumerator() { if (this.database != null) { return new TableEnumerator(this.database); } else { return new TableEnumerator(this.Dictionary.GetEnumerator()); } } /// /// Fetches an enumerator containing all the tables in this database /// /// /// 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(); } /// /// Adds the specified table definition. /// /// The table definition. internal void Add(TableDefinition tableDefinition) { this.Dictionary.Add(tableDefinition.Name.ToLower(CultureInfo.InvariantCulture), tableDefinition); } /// /// Removes the specified table name. /// /// Name of the table. internal void Remove(string tableName) { Dictionary.Remove(tableName.ToLower(CultureInfo.InvariantCulture)); } /// /// 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 TableDefinition;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 TableDefinition)) { throw new ArgumentException("value must be of type TableDefinition", "value"); } if (((string)key).ToLower(CultureInfo.InvariantCulture) != ((TableDefinition)value).Name.ToLower(CultureInfo.InvariantCulture)) { throw new ArgumentException("key must match value.Name", "key"); } } /// /// Checks the read only. /// /// this table collection cannot be changed private void CheckReadOnly() { if (this.readOnly) { throw new NotSupportedException("this table collection cannot be changed"); } } } }