DataColumnCollection.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Data / System / Data / DataColumnCollection.cs / 1305376 / DataColumnCollection.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// [....]
// [....] 
//----------------------------------------------------------------------------- 

namespace System.Data { 
    using System;
    using System.Xml;
    using System.Collections;
    using System.ComponentModel; 
    using System.Data.Common;
    using System.Diagnostics; 
 
    /// 
    /// Represents a collection of  
    /// objects for a .
    /// 
    [
    DefaultEvent("CollectionChanged"), 
    Editor("Microsoft.VSDesigner.Data.Design.ColumnsCollectionEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing),
    ] 
    public sealed class DataColumnCollection : InternalDataCollectionBase { 

        private readonly DataTable table; 
        private readonly ArrayList _list = new ArrayList();
        private int defaultNameIndex = 1;
        private DataColumn[] delayedAddRangeColumns;
 
        private readonly Hashtable columnFromName; // this hashtable contains name of colunms in this collection and name of Nested Child DataTAble
        private CollectionChangeEventHandler onCollectionChangedDelegate; 
        private CollectionChangeEventHandler onCollectionChangingDelegate; 

        private CollectionChangeEventHandler onColumnPropertyChangedDelegate; 

        private bool fInClear;

        private DataColumn[] columnsImplementingIChangeTracking = DataTable.zeroColumns; 
        private int nColumnsImplementingIChangeTracking = 0;
        private int nColumnsImplementingIRevertibleChangeTracking = 0; 
 
        /// 
        /// DataColumnCollection constructor.  Used only by DataTable. 
        /// 
        internal DataColumnCollection(DataTable table) {
            this.table = table;
            columnFromName = new Hashtable(); 
        }
 
        ///  
        ///    Gets the list of the collection items.
        ///  
        protected override ArrayList List {
            get {
                return _list;
            } 
        }
 
        internal DataColumn[] ColumnsImplementingIChangeTracking { 
            get {
                return columnsImplementingIChangeTracking; 
            }
        }
        internal int ColumnsImplementingIChangeTrackingCount{
            get { 
                return nColumnsImplementingIChangeTracking;
            } 
        } 
        internal int ColumnsImplementingIRevertibleChangeTrackingCount {
            get { 
                return nColumnsImplementingIRevertibleChangeTracking;
            }
        }
        ///  
        ///    
        ///       Gets the  
        ///       from the collection at the specified index. 
        ///    
        ///  
        public DataColumn this[int index] {
            get {
                try { // Perf: use the readonly _list field directly and let ArrayList check the range
                    return (DataColumn)_list[index]; 
                }
                catch(ArgumentOutOfRangeException) { 
                    throw ExceptionBuilder.ColumnOutOfRange(index); 
                }
            } 
        }

        /// 
        /// Gets the  from the collection with the specified name. 
        /// 
        public DataColumn this[string name] { 
            get { 
                if (null == name) {
                    throw ExceptionBuilder.ArgumentNull("name"); 
                }
                DataColumn column = columnFromName[name] as DataColumn;
                if (null == column) {
                    // Case-Insensitive compares 
                    int index = IndexOfCaseInsensitive(name);
                    if (0 <= index) { 
                        column = (DataColumn)_list[index]; 
                    }
                    else if (-2 == index) { 
                        throw ExceptionBuilder.CaseInsensitiveNameConflict(name);
                    }
                }
                return column; 
            }
        } 
 
        internal DataColumn this[string name, string ns]
        { 
            get
            {
                DataColumn column =  columnFromName[name] as DataColumn;
                if (column != null && column.Namespace == ns) 
                    return column;
 
                return null; 
            }
        } 

        /// 
        /// Adds the specified 
        /// to the columns collection. 
        /// 
        public void Add(DataColumn column) { 
            AddAt(-1, column); 
        }
 
        internal void AddAt(int index, DataColumn column) {
            if (column != null && column.ColumnMapping == MappingType.SimpleContent) {
                if (table.XmlText != null && table.XmlText != column)
                    throw ExceptionBuilder.CannotAddColumn3(); 
                if (table.ElementColumnCount > 0)
                    throw ExceptionBuilder.CannotAddColumn4(column.ColumnName); 
                OnCollectionChanging(new CollectionChangeEventArgs(CollectionChangeAction.Add, column)); 
                BaseAdd(column);
                if (index != -1) 
                    ArrayAdd(index, column);
                else
                    ArrayAdd(column);
 
                table.XmlText = column;
            } 
            else { 
                OnCollectionChanging(new CollectionChangeEventArgs(CollectionChangeAction.Add, column));
                BaseAdd(column); 
                if (index != -1)
                    ArrayAdd(index, column);
                else
                    ArrayAdd(column); 
                // if the column is an element increase the internal dataTable counter
                if (column.ColumnMapping == MappingType.Element) 
                    table.ElementColumnCount ++; 
            }
            if (!table.fInitInProgress && column != null && column.Computed) { 
                column.Expression = column.Expression;
            }
            OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Add, column));
        } 
        /// 
        ///    [To be supplied.] 
        ///  
        public void AddRange(DataColumn[] columns) {
            if (table.fInitInProgress) { 
                delayedAddRangeColumns = columns;
                return;
            }
 
            if (columns != null) {
                foreach(DataColumn column in columns) { 
                    if (column != null) { 
                        Add(column);
                    } 
                }
            }
        }
 
        /// 
        /// Creates and adds a  
        /// with 
        /// the specified name, type, and compute expression to the columns collection.
        ///  
        public DataColumn Add(string columnName, Type type, string expression) {
            DataColumn column = new DataColumn(columnName, type, expression);
            Add(column);
            return column; 
        }
 
        ///  
        /// Creates and adds a 
        /// with the 
        /// specified name and type to the columns collection.
        /// 
        public DataColumn Add(string columnName, Type type) {
            DataColumn column = new DataColumn(columnName, type); 
            Add(column);
            return column; 
        } 

        ///  
        /// Creates and adds a 
        /// with the specified name to the columns collection.
        /// 
        public DataColumn Add(string columnName) { 
            DataColumn column = new DataColumn(columnName);
            Add(column); 
            return column; 
        }
 
        /// 
        /// Creates and adds a  to a columns collection.
        /// 
        public DataColumn Add() { 
            DataColumn column = new DataColumn();
            Add(column); 
            return column; 
        }
 

        /// 
        ///    Occurs when the columns collection changes, either by adding or removing a column.
        ///  
        [ResDescriptionAttribute(Res.collectionChangedEventDescr)]
        public event CollectionChangeEventHandler CollectionChanged { 
            add { 
                onCollectionChangedDelegate += value;
            } 
            remove {
                onCollectionChangedDelegate -= value;
            }
        } 

        internal event CollectionChangeEventHandler CollectionChanging { 
            add { 
                onCollectionChangingDelegate += value;
            } 
            remove {
                onCollectionChangingDelegate -= value;
            }
        } 

        internal event CollectionChangeEventHandler ColumnPropertyChanged { 
            add { 
                onColumnPropertyChangedDelegate += value;
            } 
            remove {
                onColumnPropertyChangedDelegate -= value;
            }
        } 

        ///  
        ///  Adds the column to the columns array. 
        /// 
        private void ArrayAdd(DataColumn column) { 
            _list.Add(column);
            column.SetOrdinalInternal(_list.Count - 1);
            CheckIChangeTracking(column);
        } 

        private void ArrayAdd(int index, DataColumn column) { 
            _list.Insert(index, column); 
            CheckIChangeTracking(column);
        } 

        private void ArrayRemove(DataColumn column) {
            column.SetOrdinalInternal(-1);
            _list.Remove(column); 

            int count = _list.Count; 
            for (int i =0; i < count; i++) { 
                ((DataColumn) _list[i]).SetOrdinalInternal(i);
            } 
            if (column.ImplementsIChangeTracking) {
                RemoveColumnsImplementingIChangeTrackingList(column);
            }
        } 

        ///  
        /// Creates a new default name. 
        /// 
        internal string AssignName() { 
            string newName = MakeName(defaultNameIndex++);

            while (columnFromName[newName] != null)
                newName = MakeName(defaultNameIndex++); 

            return newName; 
        } 

        ///  
        /// Does verification on the column and it's name, and points the column at the dataSet that owns this collection.
        /// An ArgumentNullException is thrown if this column is null.  An ArgumentException is thrown if this column
        /// already belongs to this collection, belongs to another collection.
        /// A DuplicateNameException is thrown if this collection already has a column with the same 
        /// name (case insensitive).
        ///  
        private void BaseAdd(DataColumn column) { 
            if (column == null)
                throw ExceptionBuilder.ArgumentNull("column"); 
            if (column.table == table)
                throw ExceptionBuilder.CannotAddColumn1(column.ColumnName);
            if (column.table != null)
                throw ExceptionBuilder.CannotAddColumn2(column.ColumnName); 

            if (column.ColumnName.Length == 0) { 
                column.ColumnName = AssignName(); 
            }
            RegisterColumnName(column.ColumnName, column, (DataTable)null); 
            try {
                column.SetTable(table);
                if (!table.fInitInProgress && column.Computed) {
                    if (column.DataExpression.DependsOn(column)) { 
                        throw ExceptionBuilder.ExpressionCircular();
                    } 
                } 

                if (0 < table.RecordCapacity) { 
                    // adding a column to table with existing rows
                    column.SetCapacity(table.RecordCapacity);
                }
 
                // fill column with default value.
                for (int record = 0; record < table.RecordCapacity; record++) { 
                    column.InitializeRecord(record); 
                }
 
                if (table.DataSet != null) {
                    column.OnSetDataSet();
                }
            } 
            catch (Exception e) {
                // 
                if (ADP.IsCatchableOrSecurityExceptionType(e)) { 
                    UnregisterName(column.ColumnName);
                } 
                throw;
            }
        }
 
        /// 
        /// BaseGroupSwitch will intelligently remove and add tables from the collection. 
        ///  
        private void BaseGroupSwitch(DataColumn[] oldArray, int oldLength, DataColumn[] newArray, int newLength) {
            // We're doing a smart diff of oldArray and newArray to find out what 
            // should be removed.  We'll pass through oldArray and see if it exists
            // in newArray, and if not, do remove work.  newBase is an opt. in case
            // the arrays have similar prefixes.
            int newBase = 0; 
            for (int oldCur = 0; oldCur < oldLength; oldCur++) {
                bool found = false; 
                for (int newCur = newBase; newCur < newLength; newCur++) { 
                    if (oldArray[oldCur] == newArray[newCur]) {
                        if (newBase == newCur) { 
                            newBase++;
                        }
                        found = true;
                        break; 
                    }
                } 
                if (!found) { 
                    // This means it's in oldArray and not newArray.  Remove it.
                    if (oldArray[oldCur].Table == table) { 
                        BaseRemove(oldArray[oldCur]);
                        _list.Remove(oldArray[oldCur]);
                        oldArray[oldCur].SetOrdinalInternal(-1);
                    } 
                }
            } 
 
            // Now, let's pass through news and those that don't belong, add them.
            for (int newCur = 0; newCur < newLength; newCur++) { 
                if (newArray[newCur].Table != table) {
                    BaseAdd(newArray[newCur]);
                    _list.Add(newArray[newCur]);
                } 
                newArray[newCur].SetOrdinalInternal(newCur);
            } 
        } 

        ///  
        /// Does verification on the column and it's name, and clears the column's dataSet pointer.
        /// An ArgumentNullException is thrown if this column is null.  An ArgumentException is thrown
        /// if this column doesn't belong to this collection or if this column is part of a relationship.
        /// An ArgumentException is thrown if another column's compute expression depends on this column. 
        /// 
        private void BaseRemove(DataColumn column) { 
            if (CanRemove(column, true)) { 

                // remove 
                if (column.errors > 0) {
                    for (int i = 0; i < table.Rows.Count; i++) {
                        table.Rows[i].ClearError(column);
                    } 
                }
                UnregisterName(column.ColumnName); 
                column.SetTable(null); 
            }
        } 

        /// 
        ///    Checks
        ///       if 
        ///       a given column can be removed from the collection.
        ///  
        public bool CanRemove(DataColumn column) { 
            return CanRemove(column, false);
        } 

        internal bool CanRemove(DataColumn column, bool fThrowException) {
            if (column == null) {
                if (!fThrowException) 
                    return false;
                else 
                throw ExceptionBuilder.ArgumentNull("column"); 
            }
            if (column.table != table) { 
                if (!fThrowException)
                    return false;
                else
                throw ExceptionBuilder.CannotRemoveColumn(); 
            }
 
            // allow subclasses to complain first. 
            table.OnRemoveColumnInternal(column);
 
            // We need to make sure the column is not involved in any Relations or Constriants
            if (table.primaryKey != null && table.primaryKey.Key.ContainsColumn(column)) {
                if (!fThrowException)
                    return false; 
                else
                throw ExceptionBuilder.CannotRemovePrimaryKey(); 
            } 
            for (int i = 0; i < table.ParentRelations.Count; i++) {
                if (table.ParentRelations[i].ChildKey.ContainsColumn(column)) { 
                    if (!fThrowException)
                        return false;
                    else
                    throw ExceptionBuilder.CannotRemoveChildKey(table.ParentRelations[i].RelationName); 
                }
            } 
            for (int i = 0; i < table.ChildRelations.Count; i++) { 
                if (table.ChildRelations[i].ParentKey.ContainsColumn(column)) {
                    if (!fThrowException) 
                        return false;
                    else
                    throw ExceptionBuilder.CannotRemoveChildKey(table.ChildRelations[i].RelationName);
                } 
            }
            for (int i = 0; i < table.Constraints.Count; i++) { 
                if (table.Constraints[i].ContainsColumn(column)) 
                    if (!fThrowException)
                        return false; 
                    else
                    throw ExceptionBuilder.CannotRemoveConstraint(table.Constraints[i].ConstraintName, table.Constraints[i].Table.TableName);
            }
            if (table.DataSet != null) { 
                for (ParentForeignKeyConstraintEnumerator en = new ParentForeignKeyConstraintEnumerator(table.DataSet, table); en.GetNext();) {
                    Constraint constraint = en.GetConstraint(); 
                    if (((ForeignKeyConstraint)constraint).ParentKey.ContainsColumn(column)) 
                        if (!fThrowException)
                            return false; 
                        else
                            throw ExceptionBuilder.CannotRemoveConstraint(constraint.ConstraintName, constraint.Table.TableName);
                }
            } 

            if (column.dependentColumns != null) { 
                for (int i = 0; i < column.dependentColumns.Count; i++) { 
                    DataColumn col = column.dependentColumns[i];
                    if (fInClear && (col.Table == table || col.Table == null)) 
                        continue;
                    if (col.Table == null)
                        continue;
                    Debug.Assert(col.Computed, "invalid (non an expression) column in the expression dependent columns"); 
                    DataExpression expr = col.DataExpression;
                    if ((expr!= null) && (expr.DependsOn(column))) { 
                        if (!fThrowException) 
                            return false;
                        else 
                            throw ExceptionBuilder.CannotRemoveExpression(col.ColumnName, col.Expression);
                    }
                }
            } 

            // SQLBU 429176: you can't remove a column participating in an index, 
            // while index events are suspended else the indexes won't be properly maintained. 
            // However, all the above checks should catch those participating columns.
            // except when a column is in a DataView RowFilter or Sort clause 
            foreach (Index index in table.LiveIndexes) {
#if false
                if (!Object.ReferenceEquals(index, column.sortIndex)) {
                    foreach (IndexField field in index.IndexFields) { 
                        if (Object.ReferenceEquals(field.Column, column)) {
                            if (fThrowException) { 
                                throw ExceptionBuilder.CannotRemoveExpression("DataView", column.ColumnName); 
                            }
                            return false; 
                        }
                    }
                }
#endif 
            }
 
            return true; 
        }
 
        private void CheckIChangeTracking(DataColumn column) {
            if (column.ImplementsIRevertibleChangeTracking) {
                nColumnsImplementingIRevertibleChangeTracking++;
                nColumnsImplementingIChangeTracking++; 
                AddColumnsImplementingIChangeTrackingList(column);
            } 
            else if (column.ImplementsIChangeTracking) { 
                nColumnsImplementingIChangeTracking++;
                AddColumnsImplementingIChangeTrackingList(column); 
            }
        }

        ///  
        ///    
        ///       Clears the collection of any columns. 
        ///     
        /// 
        public void Clear() { 
            int oldLength = _list.Count;

            DataColumn[] columns = new DataColumn[_list.Count];
            _list.CopyTo(columns, 0); 

            OnCollectionChanging(RefreshEventArgs); 
 
            if (table.fInitInProgress && delayedAddRangeColumns != null) {
                delayedAddRangeColumns = null; 
            }

            try {
                // this will smartly add and remove the appropriate tables. 
                fInClear = true;
                BaseGroupSwitch(columns, oldLength, null, 0); 
                fInClear = false; 
            }
            catch (Exception e) { 
                //
                if (ADP.IsCatchableOrSecurityExceptionType(e)) {
                    // something messed up: restore to old values and throw
                    fInClear = false; 
                    BaseGroupSwitch(null, 0, columns, oldLength);
                    _list.Clear(); 
                    for (int i = 0; i < oldLength; i++) 
                        _list.Add(columns[i]);
                } 
                throw;
            }
            _list.Clear();
            table.ElementColumnCount  = 0; 
            OnCollectionChanged(RefreshEventArgs);
        } 
 
        /// 
        ///    Checks whether the collection contains a column with the specified name. 
        /// 
        public bool Contains(string name) {
            DataColumn column =  columnFromName[name] as DataColumn;
            if (column != null) { 
                return true;
            } 
 
            return (IndexOfCaseInsensitive(name) >= 0);
        } 

        internal bool Contains(string name, bool caseSensitive) {
            DataColumn column =  columnFromName[name] as DataColumn;
            if (column != null) { 
                return true;
            } 
 
            if (caseSensitive) { // above check did case sensitive check
                return false; 
            }
            else {
                return (IndexOfCaseInsensitive(name) >= 0);
            } 
        }
 
        public void CopyTo(DataColumn[] array, int index) { 
            if (array==null)
                throw ExceptionBuilder.ArgumentNull("array"); 
            if (index < 0)
                throw ExceptionBuilder.ArgumentOutOfRange("index");
            if (array.Length - index < _list.Count)
                throw ExceptionBuilder.InvalidOffsetLength(); 
            for(int i = 0; i < _list.Count; ++i) {
                array[index + i] = (DataColumn)_list[i]; 
            } 
        }
 
        /// 
        ///    
        ///       Returns the index of a specified .
        ///     
        /// 
        public int IndexOf(DataColumn column) { 
            int columnCount = _list.Count; 
            for (int i = 0; i < columnCount; ++i) {
                if (column == (DataColumn) _list[i]) { 
                    return i;
                }
            }
            return -1; 
        }
 
        ///  
        ///    Returns the index of
        ///       a column specified by name. 
        /// 
        public int IndexOf(string columnName) {

            if ((null != columnName) && (0 < columnName.Length)) { 
                int count = Count;
                DataColumn column = columnFromName[columnName] as DataColumn; 
 
                if (column != null) {
                    for (int j = 0; j < count; j++) 
                        if (column == _list[j]) {
                            return j;
                        }
                } 
                else {
                    int res = IndexOfCaseInsensitive(columnName); 
                    return (res < 0) ? -1 : res; 
                }
            } 
            return -1;
        }

        internal int IndexOfCaseInsensitive (string name) { 
            int hashcode = table.GetSpecialHashCode(name);
            int cachedI = -1; 
            DataColumn column = null; 
            for (int i = 0; i < Count; i++) {
                column = (DataColumn) _list[i]; 
                if ( (hashcode == 0 || column._hashCode == 0 || column._hashCode == hashcode) &&
                   NamesEqual(column.ColumnName, name, false, table.Locale) != 0 ) {
                    if (cachedI == -1)
                        cachedI = i; 
                    else
                        return -2; 
                } 
            }
            return cachedI; 
        }

        internal void FinishInitCollection() {
            if (delayedAddRangeColumns != null) { 
                foreach(DataColumn column in delayedAddRangeColumns) {
                    if (column != null) { 
                        Add(column); 
                    }
                } 

                foreach(DataColumn column in delayedAddRangeColumns) {
                    if (column != null) {
                        column.FinishInitInProgress(); 
                    }
                } 
 
                delayedAddRangeColumns = null;
            } 
        }

        /// 
        /// Makes a default name with the given index.  e.g. Column1, Column2, ... Columni 
        /// 
        private string MakeName(int index) { 
            if (1 == index) { 
                return "Column1";
            } 
            return "Column" + index.ToString(System.Globalization.CultureInfo.InvariantCulture);
        }

        internal void MoveTo(DataColumn column, int newPosition) { 
            if (0 > newPosition || newPosition > Count -1) {
                throw ExceptionBuilder.InvalidOrdinal("ordinal", newPosition); 
            } 
            if (column.ImplementsIChangeTracking) {
                RemoveColumnsImplementingIChangeTrackingList(column); 
            }
            _list.Remove(column);
            _list.Insert(newPosition, column);
            int count = _list.Count; 
            for (int i =0; i < count; i++) {
                ((DataColumn) _list[i]).SetOrdinalInternal(i); 
            } 
            CheckIChangeTracking(column);
            OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Refresh, column)); 
        }

        /// 
        ///     
        ///       Raises the  event.
        ///     
        ///  
        private void OnCollectionChanged(CollectionChangeEventArgs ccevent) {
            table.UpdatePropertyDescriptorCollectionCache(); 

            if ((null != ccevent) && !table.SchemaLoading && !table.fInitInProgress) {
                DataColumn column = (DataColumn)ccevent.Element;
            } 
            if (onCollectionChangedDelegate != null) {
                onCollectionChangedDelegate(this, ccevent); 
            } 
        }
 
        /// 
        ///    [To be supplied.]
        /// 
        private void OnCollectionChanging(CollectionChangeEventArgs ccevent) { 
            if (onCollectionChangingDelegate != null) {
                onCollectionChangingDelegate(this, ccevent); 
            } 
        }
 
        internal void OnColumnPropertyChanged(CollectionChangeEventArgs ccevent) {
            table.UpdatePropertyDescriptorCollectionCache();
            if (onColumnPropertyChangedDelegate != null) {
                onColumnPropertyChangedDelegate(this, ccevent); 
            }
        } 
 
        /// 
        /// Registers this name as being used in the collection.  Will throw an ArgumentException 
        /// if the name is already being used.  Called by Add, All property, and Column.ColumnName property.
        /// if the name is equivalent to the next default name to hand out, we increment our defaultNameIndex.
        /// 
        internal void RegisterColumnName(string name, DataColumn column, DataTable table) { 
            Debug.Assert (name != null);
            Debug.Assert ((null == column) != (null == table), "RegisterColumnName wrong usage"); 
            Object _exObject = columnFromName[name]; 

            if (_exObject != null) { 
                if (_exObject is DataColumn) {
                    if (null != column) {
                        throw ExceptionBuilder.CannotAddDuplicate(name);
                    } 
                    else {
                        throw ExceptionBuilder.CannotAddDuplicate3(name); 
                    } 
                }
                throw ExceptionBuilder.CannotAddDuplicate2(name); 
            }

            //we need to check wether the tableName is the same of the
            //next generable columnName and update defaultNameIndex accordingly 
            if ((null != table) && NamesEqual(name, MakeName(defaultNameIndex), true, this.table.Locale) != 0) {
                do { 
                    defaultNameIndex++; 
                } while (Contains(MakeName(defaultNameIndex)));
            } 

            if (null != column) {
                column._hashCode = this.table.GetSpecialHashCode(name);
                columnFromName.Add(name, column); 
            }
            else { 
                columnFromName.Add(name, table); 
            }
        } 

        internal bool CanRegisterName(string name) {
            Debug.Assert (name != null);
            return (null == columnFromName[name]); 
        }
 
        ///  
        /// Removes the specified 
        /// from the collection. 
        /// 
        public void Remove(DataColumn column) {
            OnCollectionChanging(new CollectionChangeEventArgs(CollectionChangeAction.Remove, column));
            BaseRemove(column); 
            ArrayRemove(column);
            OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Remove, column)); 
            // if the column is an element decrease the internal dataTable counter 
            if (column.ColumnMapping == MappingType.Element)
                table.ElementColumnCount --; 
        }

        /// 
        ///    Removes the 
        ///       column at the specified index from the collection.
        ///  
        public void RemoveAt(int index) { 
            DataColumn dc = this[index];
            if (dc == null) 
                throw ExceptionBuilder.ColumnOutOfRange(index);
            Remove(dc);
        }
 
        /// 
        ///    Removes the 
        ///       column with the specified name from the collection. 
        /// 
        public void Remove(string name) { 
            DataColumn dc = this[name];
            if (dc == null)
                throw ExceptionBuilder.ColumnNotInTheTable(name, table.TableName);
            Remove(dc); 
        }
 
        ///  
        /// Unregisters this name as no longer being used in the collection.  Called by Remove, All property, and
        /// Column.ColumnName property.  If the name is equivalent to the last proposed default namem, we walk backwards 
        /// to find the next proper default name to hang out.
        /// 
        internal void UnregisterName(string name) {
            Object obj = columnFromName[name]; 
            if (obj != null)                 // sinc the HashTable is case-sensitive
                columnFromName.Remove(name); // this is totally equivalent 
 

            if (NamesEqual(name, MakeName(defaultNameIndex - 1), true, table.Locale) != 0) { 
                do {
                    defaultNameIndex--;
                } while (defaultNameIndex > 1 &&
                         !Contains(MakeName(defaultNameIndex - 1))); 
            }
        } 
 
        private void AddColumnsImplementingIChangeTrackingList(DataColumn dataColumn) {
            DataColumn[] columns = columnsImplementingIChangeTracking; 
            DataColumn[] tempColumns = new DataColumn[columns.Length +1];
            columns.CopyTo(tempColumns, 0);
            tempColumns[columns.Length] = dataColumn;
            columnsImplementingIChangeTracking = tempColumns; 
        }
 
        private void RemoveColumnsImplementingIChangeTrackingList(DataColumn dataColumn) { 
            DataColumn[] columns = columnsImplementingIChangeTracking;
            DataColumn[] tempColumns = new DataColumn[columns.Length - 1]; 
            for(int i = 0, j = 0; i < columns.Length; i++) {
                if (columns[i] != dataColumn) {
                    tempColumns[j++] = columns[i];
                } 
            }
            columnsImplementingIChangeTracking = tempColumns; 
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// [....]
// [....] 
//----------------------------------------------------------------------------- 

namespace System.Data { 
    using System;
    using System.Xml;
    using System.Collections;
    using System.ComponentModel; 
    using System.Data.Common;
    using System.Diagnostics; 
 
    /// 
    /// Represents a collection of  
    /// objects for a .
    /// 
    [
    DefaultEvent("CollectionChanged"), 
    Editor("Microsoft.VSDesigner.Data.Design.ColumnsCollectionEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing),
    ] 
    public sealed class DataColumnCollection : InternalDataCollectionBase { 

        private readonly DataTable table; 
        private readonly ArrayList _list = new ArrayList();
        private int defaultNameIndex = 1;
        private DataColumn[] delayedAddRangeColumns;
 
        private readonly Hashtable columnFromName; // this hashtable contains name of colunms in this collection and name of Nested Child DataTAble
        private CollectionChangeEventHandler onCollectionChangedDelegate; 
        private CollectionChangeEventHandler onCollectionChangingDelegate; 

        private CollectionChangeEventHandler onColumnPropertyChangedDelegate; 

        private bool fInClear;

        private DataColumn[] columnsImplementingIChangeTracking = DataTable.zeroColumns; 
        private int nColumnsImplementingIChangeTracking = 0;
        private int nColumnsImplementingIRevertibleChangeTracking = 0; 
 
        /// 
        /// DataColumnCollection constructor.  Used only by DataTable. 
        /// 
        internal DataColumnCollection(DataTable table) {
            this.table = table;
            columnFromName = new Hashtable(); 
        }
 
        ///  
        ///    Gets the list of the collection items.
        ///  
        protected override ArrayList List {
            get {
                return _list;
            } 
        }
 
        internal DataColumn[] ColumnsImplementingIChangeTracking { 
            get {
                return columnsImplementingIChangeTracking; 
            }
        }
        internal int ColumnsImplementingIChangeTrackingCount{
            get { 
                return nColumnsImplementingIChangeTracking;
            } 
        } 
        internal int ColumnsImplementingIRevertibleChangeTrackingCount {
            get { 
                return nColumnsImplementingIRevertibleChangeTracking;
            }
        }
        ///  
        ///    
        ///       Gets the  
        ///       from the collection at the specified index. 
        ///    
        ///  
        public DataColumn this[int index] {
            get {
                try { // Perf: use the readonly _list field directly and let ArrayList check the range
                    return (DataColumn)_list[index]; 
                }
                catch(ArgumentOutOfRangeException) { 
                    throw ExceptionBuilder.ColumnOutOfRange(index); 
                }
            } 
        }

        /// 
        /// Gets the  from the collection with the specified name. 
        /// 
        public DataColumn this[string name] { 
            get { 
                if (null == name) {
                    throw ExceptionBuilder.ArgumentNull("name"); 
                }
                DataColumn column = columnFromName[name] as DataColumn;
                if (null == column) {
                    // Case-Insensitive compares 
                    int index = IndexOfCaseInsensitive(name);
                    if (0 <= index) { 
                        column = (DataColumn)_list[index]; 
                    }
                    else if (-2 == index) { 
                        throw ExceptionBuilder.CaseInsensitiveNameConflict(name);
                    }
                }
                return column; 
            }
        } 
 
        internal DataColumn this[string name, string ns]
        { 
            get
            {
                DataColumn column =  columnFromName[name] as DataColumn;
                if (column != null && column.Namespace == ns) 
                    return column;
 
                return null; 
            }
        } 

        /// 
        /// Adds the specified 
        /// to the columns collection. 
        /// 
        public void Add(DataColumn column) { 
            AddAt(-1, column); 
        }
 
        internal void AddAt(int index, DataColumn column) {
            if (column != null && column.ColumnMapping == MappingType.SimpleContent) {
                if (table.XmlText != null && table.XmlText != column)
                    throw ExceptionBuilder.CannotAddColumn3(); 
                if (table.ElementColumnCount > 0)
                    throw ExceptionBuilder.CannotAddColumn4(column.ColumnName); 
                OnCollectionChanging(new CollectionChangeEventArgs(CollectionChangeAction.Add, column)); 
                BaseAdd(column);
                if (index != -1) 
                    ArrayAdd(index, column);
                else
                    ArrayAdd(column);
 
                table.XmlText = column;
            } 
            else { 
                OnCollectionChanging(new CollectionChangeEventArgs(CollectionChangeAction.Add, column));
                BaseAdd(column); 
                if (index != -1)
                    ArrayAdd(index, column);
                else
                    ArrayAdd(column); 
                // if the column is an element increase the internal dataTable counter
                if (column.ColumnMapping == MappingType.Element) 
                    table.ElementColumnCount ++; 
            }
            if (!table.fInitInProgress && column != null && column.Computed) { 
                column.Expression = column.Expression;
            }
            OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Add, column));
        } 
        /// 
        ///    [To be supplied.] 
        ///  
        public void AddRange(DataColumn[] columns) {
            if (table.fInitInProgress) { 
                delayedAddRangeColumns = columns;
                return;
            }
 
            if (columns != null) {
                foreach(DataColumn column in columns) { 
                    if (column != null) { 
                        Add(column);
                    } 
                }
            }
        }
 
        /// 
        /// Creates and adds a  
        /// with 
        /// the specified name, type, and compute expression to the columns collection.
        ///  
        public DataColumn Add(string columnName, Type type, string expression) {
            DataColumn column = new DataColumn(columnName, type, expression);
            Add(column);
            return column; 
        }
 
        ///  
        /// Creates and adds a 
        /// with the 
        /// specified name and type to the columns collection.
        /// 
        public DataColumn Add(string columnName, Type type) {
            DataColumn column = new DataColumn(columnName, type); 
            Add(column);
            return column; 
        } 

        ///  
        /// Creates and adds a 
        /// with the specified name to the columns collection.
        /// 
        public DataColumn Add(string columnName) { 
            DataColumn column = new DataColumn(columnName);
            Add(column); 
            return column; 
        }
 
        /// 
        /// Creates and adds a  to a columns collection.
        /// 
        public DataColumn Add() { 
            DataColumn column = new DataColumn();
            Add(column); 
            return column; 
        }
 

        /// 
        ///    Occurs when the columns collection changes, either by adding or removing a column.
        ///  
        [ResDescriptionAttribute(Res.collectionChangedEventDescr)]
        public event CollectionChangeEventHandler CollectionChanged { 
            add { 
                onCollectionChangedDelegate += value;
            } 
            remove {
                onCollectionChangedDelegate -= value;
            }
        } 

        internal event CollectionChangeEventHandler CollectionChanging { 
            add { 
                onCollectionChangingDelegate += value;
            } 
            remove {
                onCollectionChangingDelegate -= value;
            }
        } 

        internal event CollectionChangeEventHandler ColumnPropertyChanged { 
            add { 
                onColumnPropertyChangedDelegate += value;
            } 
            remove {
                onColumnPropertyChangedDelegate -= value;
            }
        } 

        ///  
        ///  Adds the column to the columns array. 
        /// 
        private void ArrayAdd(DataColumn column) { 
            _list.Add(column);
            column.SetOrdinalInternal(_list.Count - 1);
            CheckIChangeTracking(column);
        } 

        private void ArrayAdd(int index, DataColumn column) { 
            _list.Insert(index, column); 
            CheckIChangeTracking(column);
        } 

        private void ArrayRemove(DataColumn column) {
            column.SetOrdinalInternal(-1);
            _list.Remove(column); 

            int count = _list.Count; 
            for (int i =0; i < count; i++) { 
                ((DataColumn) _list[i]).SetOrdinalInternal(i);
            } 
            if (column.ImplementsIChangeTracking) {
                RemoveColumnsImplementingIChangeTrackingList(column);
            }
        } 

        ///  
        /// Creates a new default name. 
        /// 
        internal string AssignName() { 
            string newName = MakeName(defaultNameIndex++);

            while (columnFromName[newName] != null)
                newName = MakeName(defaultNameIndex++); 

            return newName; 
        } 

        ///  
        /// Does verification on the column and it's name, and points the column at the dataSet that owns this collection.
        /// An ArgumentNullException is thrown if this column is null.  An ArgumentException is thrown if this column
        /// already belongs to this collection, belongs to another collection.
        /// A DuplicateNameException is thrown if this collection already has a column with the same 
        /// name (case insensitive).
        ///  
        private void BaseAdd(DataColumn column) { 
            if (column == null)
                throw ExceptionBuilder.ArgumentNull("column"); 
            if (column.table == table)
                throw ExceptionBuilder.CannotAddColumn1(column.ColumnName);
            if (column.table != null)
                throw ExceptionBuilder.CannotAddColumn2(column.ColumnName); 

            if (column.ColumnName.Length == 0) { 
                column.ColumnName = AssignName(); 
            }
            RegisterColumnName(column.ColumnName, column, (DataTable)null); 
            try {
                column.SetTable(table);
                if (!table.fInitInProgress && column.Computed) {
                    if (column.DataExpression.DependsOn(column)) { 
                        throw ExceptionBuilder.ExpressionCircular();
                    } 
                } 

                if (0 < table.RecordCapacity) { 
                    // adding a column to table with existing rows
                    column.SetCapacity(table.RecordCapacity);
                }
 
                // fill column with default value.
                for (int record = 0; record < table.RecordCapacity; record++) { 
                    column.InitializeRecord(record); 
                }
 
                if (table.DataSet != null) {
                    column.OnSetDataSet();
                }
            } 
            catch (Exception e) {
                // 
                if (ADP.IsCatchableOrSecurityExceptionType(e)) { 
                    UnregisterName(column.ColumnName);
                } 
                throw;
            }
        }
 
        /// 
        /// BaseGroupSwitch will intelligently remove and add tables from the collection. 
        ///  
        private void BaseGroupSwitch(DataColumn[] oldArray, int oldLength, DataColumn[] newArray, int newLength) {
            // We're doing a smart diff of oldArray and newArray to find out what 
            // should be removed.  We'll pass through oldArray and see if it exists
            // in newArray, and if not, do remove work.  newBase is an opt. in case
            // the arrays have similar prefixes.
            int newBase = 0; 
            for (int oldCur = 0; oldCur < oldLength; oldCur++) {
                bool found = false; 
                for (int newCur = newBase; newCur < newLength; newCur++) { 
                    if (oldArray[oldCur] == newArray[newCur]) {
                        if (newBase == newCur) { 
                            newBase++;
                        }
                        found = true;
                        break; 
                    }
                } 
                if (!found) { 
                    // This means it's in oldArray and not newArray.  Remove it.
                    if (oldArray[oldCur].Table == table) { 
                        BaseRemove(oldArray[oldCur]);
                        _list.Remove(oldArray[oldCur]);
                        oldArray[oldCur].SetOrdinalInternal(-1);
                    } 
                }
            } 
 
            // Now, let's pass through news and those that don't belong, add them.
            for (int newCur = 0; newCur < newLength; newCur++) { 
                if (newArray[newCur].Table != table) {
                    BaseAdd(newArray[newCur]);
                    _list.Add(newArray[newCur]);
                } 
                newArray[newCur].SetOrdinalInternal(newCur);
            } 
        } 

        ///  
        /// Does verification on the column and it's name, and clears the column's dataSet pointer.
        /// An ArgumentNullException is thrown if this column is null.  An ArgumentException is thrown
        /// if this column doesn't belong to this collection or if this column is part of a relationship.
        /// An ArgumentException is thrown if another column's compute expression depends on this column. 
        /// 
        private void BaseRemove(DataColumn column) { 
            if (CanRemove(column, true)) { 

                // remove 
                if (column.errors > 0) {
                    for (int i = 0; i < table.Rows.Count; i++) {
                        table.Rows[i].ClearError(column);
                    } 
                }
                UnregisterName(column.ColumnName); 
                column.SetTable(null); 
            }
        } 

        /// 
        ///    Checks
        ///       if 
        ///       a given column can be removed from the collection.
        ///  
        public bool CanRemove(DataColumn column) { 
            return CanRemove(column, false);
        } 

        internal bool CanRemove(DataColumn column, bool fThrowException) {
            if (column == null) {
                if (!fThrowException) 
                    return false;
                else 
                throw ExceptionBuilder.ArgumentNull("column"); 
            }
            if (column.table != table) { 
                if (!fThrowException)
                    return false;
                else
                throw ExceptionBuilder.CannotRemoveColumn(); 
            }
 
            // allow subclasses to complain first. 
            table.OnRemoveColumnInternal(column);
 
            // We need to make sure the column is not involved in any Relations or Constriants
            if (table.primaryKey != null && table.primaryKey.Key.ContainsColumn(column)) {
                if (!fThrowException)
                    return false; 
                else
                throw ExceptionBuilder.CannotRemovePrimaryKey(); 
            } 
            for (int i = 0; i < table.ParentRelations.Count; i++) {
                if (table.ParentRelations[i].ChildKey.ContainsColumn(column)) { 
                    if (!fThrowException)
                        return false;
                    else
                    throw ExceptionBuilder.CannotRemoveChildKey(table.ParentRelations[i].RelationName); 
                }
            } 
            for (int i = 0; i < table.ChildRelations.Count; i++) { 
                if (table.ChildRelations[i].ParentKey.ContainsColumn(column)) {
                    if (!fThrowException) 
                        return false;
                    else
                    throw ExceptionBuilder.CannotRemoveChildKey(table.ChildRelations[i].RelationName);
                } 
            }
            for (int i = 0; i < table.Constraints.Count; i++) { 
                if (table.Constraints[i].ContainsColumn(column)) 
                    if (!fThrowException)
                        return false; 
                    else
                    throw ExceptionBuilder.CannotRemoveConstraint(table.Constraints[i].ConstraintName, table.Constraints[i].Table.TableName);
            }
            if (table.DataSet != null) { 
                for (ParentForeignKeyConstraintEnumerator en = new ParentForeignKeyConstraintEnumerator(table.DataSet, table); en.GetNext();) {
                    Constraint constraint = en.GetConstraint(); 
                    if (((ForeignKeyConstraint)constraint).ParentKey.ContainsColumn(column)) 
                        if (!fThrowException)
                            return false; 
                        else
                            throw ExceptionBuilder.CannotRemoveConstraint(constraint.ConstraintName, constraint.Table.TableName);
                }
            } 

            if (column.dependentColumns != null) { 
                for (int i = 0; i < column.dependentColumns.Count; i++) { 
                    DataColumn col = column.dependentColumns[i];
                    if (fInClear && (col.Table == table || col.Table == null)) 
                        continue;
                    if (col.Table == null)
                        continue;
                    Debug.Assert(col.Computed, "invalid (non an expression) column in the expression dependent columns"); 
                    DataExpression expr = col.DataExpression;
                    if ((expr!= null) && (expr.DependsOn(column))) { 
                        if (!fThrowException) 
                            return false;
                        else 
                            throw ExceptionBuilder.CannotRemoveExpression(col.ColumnName, col.Expression);
                    }
                }
            } 

            // SQLBU 429176: you can't remove a column participating in an index, 
            // while index events are suspended else the indexes won't be properly maintained. 
            // However, all the above checks should catch those participating columns.
            // except when a column is in a DataView RowFilter or Sort clause 
            foreach (Index index in table.LiveIndexes) {
#if false
                if (!Object.ReferenceEquals(index, column.sortIndex)) {
                    foreach (IndexField field in index.IndexFields) { 
                        if (Object.ReferenceEquals(field.Column, column)) {
                            if (fThrowException) { 
                                throw ExceptionBuilder.CannotRemoveExpression("DataView", column.ColumnName); 
                            }
                            return false; 
                        }
                    }
                }
#endif 
            }
 
            return true; 
        }
 
        private void CheckIChangeTracking(DataColumn column) {
            if (column.ImplementsIRevertibleChangeTracking) {
                nColumnsImplementingIRevertibleChangeTracking++;
                nColumnsImplementingIChangeTracking++; 
                AddColumnsImplementingIChangeTrackingList(column);
            } 
            else if (column.ImplementsIChangeTracking) { 
                nColumnsImplementingIChangeTracking++;
                AddColumnsImplementingIChangeTrackingList(column); 
            }
        }

        ///  
        ///    
        ///       Clears the collection of any columns. 
        ///     
        /// 
        public void Clear() { 
            int oldLength = _list.Count;

            DataColumn[] columns = new DataColumn[_list.Count];
            _list.CopyTo(columns, 0); 

            OnCollectionChanging(RefreshEventArgs); 
 
            if (table.fInitInProgress && delayedAddRangeColumns != null) {
                delayedAddRangeColumns = null; 
            }

            try {
                // this will smartly add and remove the appropriate tables. 
                fInClear = true;
                BaseGroupSwitch(columns, oldLength, null, 0); 
                fInClear = false; 
            }
            catch (Exception e) { 
                //
                if (ADP.IsCatchableOrSecurityExceptionType(e)) {
                    // something messed up: restore to old values and throw
                    fInClear = false; 
                    BaseGroupSwitch(null, 0, columns, oldLength);
                    _list.Clear(); 
                    for (int i = 0; i < oldLength; i++) 
                        _list.Add(columns[i]);
                } 
                throw;
            }
            _list.Clear();
            table.ElementColumnCount  = 0; 
            OnCollectionChanged(RefreshEventArgs);
        } 
 
        /// 
        ///    Checks whether the collection contains a column with the specified name. 
        /// 
        public bool Contains(string name) {
            DataColumn column =  columnFromName[name] as DataColumn;
            if (column != null) { 
                return true;
            } 
 
            return (IndexOfCaseInsensitive(name) >= 0);
        } 

        internal bool Contains(string name, bool caseSensitive) {
            DataColumn column =  columnFromName[name] as DataColumn;
            if (column != null) { 
                return true;
            } 
 
            if (caseSensitive) { // above check did case sensitive check
                return false; 
            }
            else {
                return (IndexOfCaseInsensitive(name) >= 0);
            } 
        }
 
        public void CopyTo(DataColumn[] array, int index) { 
            if (array==null)
                throw ExceptionBuilder.ArgumentNull("array"); 
            if (index < 0)
                throw ExceptionBuilder.ArgumentOutOfRange("index");
            if (array.Length - index < _list.Count)
                throw ExceptionBuilder.InvalidOffsetLength(); 
            for(int i = 0; i < _list.Count; ++i) {
                array[index + i] = (DataColumn)_list[i]; 
            } 
        }
 
        /// 
        ///    
        ///       Returns the index of a specified .
        ///     
        /// 
        public int IndexOf(DataColumn column) { 
            int columnCount = _list.Count; 
            for (int i = 0; i < columnCount; ++i) {
                if (column == (DataColumn) _list[i]) { 
                    return i;
                }
            }
            return -1; 
        }
 
        ///  
        ///    Returns the index of
        ///       a column specified by name. 
        /// 
        public int IndexOf(string columnName) {

            if ((null != columnName) && (0 < columnName.Length)) { 
                int count = Count;
                DataColumn column = columnFromName[columnName] as DataColumn; 
 
                if (column != null) {
                    for (int j = 0; j < count; j++) 
                        if (column == _list[j]) {
                            return j;
                        }
                } 
                else {
                    int res = IndexOfCaseInsensitive(columnName); 
                    return (res < 0) ? -1 : res; 
                }
            } 
            return -1;
        }

        internal int IndexOfCaseInsensitive (string name) { 
            int hashcode = table.GetSpecialHashCode(name);
            int cachedI = -1; 
            DataColumn column = null; 
            for (int i = 0; i < Count; i++) {
                column = (DataColumn) _list[i]; 
                if ( (hashcode == 0 || column._hashCode == 0 || column._hashCode == hashcode) &&
                   NamesEqual(column.ColumnName, name, false, table.Locale) != 0 ) {
                    if (cachedI == -1)
                        cachedI = i; 
                    else
                        return -2; 
                } 
            }
            return cachedI; 
        }

        internal void FinishInitCollection() {
            if (delayedAddRangeColumns != null) { 
                foreach(DataColumn column in delayedAddRangeColumns) {
                    if (column != null) { 
                        Add(column); 
                    }
                } 

                foreach(DataColumn column in delayedAddRangeColumns) {
                    if (column != null) {
                        column.FinishInitInProgress(); 
                    }
                } 
 
                delayedAddRangeColumns = null;
            } 
        }

        /// 
        /// Makes a default name with the given index.  e.g. Column1, Column2, ... Columni 
        /// 
        private string MakeName(int index) { 
            if (1 == index) { 
                return "Column1";
            } 
            return "Column" + index.ToString(System.Globalization.CultureInfo.InvariantCulture);
        }

        internal void MoveTo(DataColumn column, int newPosition) { 
            if (0 > newPosition || newPosition > Count -1) {
                throw ExceptionBuilder.InvalidOrdinal("ordinal", newPosition); 
            } 
            if (column.ImplementsIChangeTracking) {
                RemoveColumnsImplementingIChangeTrackingList(column); 
            }
            _list.Remove(column);
            _list.Insert(newPosition, column);
            int count = _list.Count; 
            for (int i =0; i < count; i++) {
                ((DataColumn) _list[i]).SetOrdinalInternal(i); 
            } 
            CheckIChangeTracking(column);
            OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Refresh, column)); 
        }

        /// 
        ///     
        ///       Raises the  event.
        ///     
        ///  
        private void OnCollectionChanged(CollectionChangeEventArgs ccevent) {
            table.UpdatePropertyDescriptorCollectionCache(); 

            if ((null != ccevent) && !table.SchemaLoading && !table.fInitInProgress) {
                DataColumn column = (DataColumn)ccevent.Element;
            } 
            if (onCollectionChangedDelegate != null) {
                onCollectionChangedDelegate(this, ccevent); 
            } 
        }
 
        /// 
        ///    [To be supplied.]
        /// 
        private void OnCollectionChanging(CollectionChangeEventArgs ccevent) { 
            if (onCollectionChangingDelegate != null) {
                onCollectionChangingDelegate(this, ccevent); 
            } 
        }
 
        internal void OnColumnPropertyChanged(CollectionChangeEventArgs ccevent) {
            table.UpdatePropertyDescriptorCollectionCache();
            if (onColumnPropertyChangedDelegate != null) {
                onColumnPropertyChangedDelegate(this, ccevent); 
            }
        } 
 
        /// 
        /// Registers this name as being used in the collection.  Will throw an ArgumentException 
        /// if the name is already being used.  Called by Add, All property, and Column.ColumnName property.
        /// if the name is equivalent to the next default name to hand out, we increment our defaultNameIndex.
        /// 
        internal void RegisterColumnName(string name, DataColumn column, DataTable table) { 
            Debug.Assert (name != null);
            Debug.Assert ((null == column) != (null == table), "RegisterColumnName wrong usage"); 
            Object _exObject = columnFromName[name]; 

            if (_exObject != null) { 
                if (_exObject is DataColumn) {
                    if (null != column) {
                        throw ExceptionBuilder.CannotAddDuplicate(name);
                    } 
                    else {
                        throw ExceptionBuilder.CannotAddDuplicate3(name); 
                    } 
                }
                throw ExceptionBuilder.CannotAddDuplicate2(name); 
            }

            //we need to check wether the tableName is the same of the
            //next generable columnName and update defaultNameIndex accordingly 
            if ((null != table) && NamesEqual(name, MakeName(defaultNameIndex), true, this.table.Locale) != 0) {
                do { 
                    defaultNameIndex++; 
                } while (Contains(MakeName(defaultNameIndex)));
            } 

            if (null != column) {
                column._hashCode = this.table.GetSpecialHashCode(name);
                columnFromName.Add(name, column); 
            }
            else { 
                columnFromName.Add(name, table); 
            }
        } 

        internal bool CanRegisterName(string name) {
            Debug.Assert (name != null);
            return (null == columnFromName[name]); 
        }
 
        ///  
        /// Removes the specified 
        /// from the collection. 
        /// 
        public void Remove(DataColumn column) {
            OnCollectionChanging(new CollectionChangeEventArgs(CollectionChangeAction.Remove, column));
            BaseRemove(column); 
            ArrayRemove(column);
            OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Remove, column)); 
            // if the column is an element decrease the internal dataTable counter 
            if (column.ColumnMapping == MappingType.Element)
                table.ElementColumnCount --; 
        }

        /// 
        ///    Removes the 
        ///       column at the specified index from the collection.
        ///  
        public void RemoveAt(int index) { 
            DataColumn dc = this[index];
            if (dc == null) 
                throw ExceptionBuilder.ColumnOutOfRange(index);
            Remove(dc);
        }
 
        /// 
        ///    Removes the 
        ///       column with the specified name from the collection. 
        /// 
        public void Remove(string name) { 
            DataColumn dc = this[name];
            if (dc == null)
                throw ExceptionBuilder.ColumnNotInTheTable(name, table.TableName);
            Remove(dc); 
        }
 
        ///  
        /// Unregisters this name as no longer being used in the collection.  Called by Remove, All property, and
        /// Column.ColumnName property.  If the name is equivalent to the last proposed default namem, we walk backwards 
        /// to find the next proper default name to hang out.
        /// 
        internal void UnregisterName(string name) {
            Object obj = columnFromName[name]; 
            if (obj != null)                 // sinc the HashTable is case-sensitive
                columnFromName.Remove(name); // this is totally equivalent 
 

            if (NamesEqual(name, MakeName(defaultNameIndex - 1), true, table.Locale) != 0) { 
                do {
                    defaultNameIndex--;
                } while (defaultNameIndex > 1 &&
                         !Contains(MakeName(defaultNameIndex - 1))); 
            }
        } 
 
        private void AddColumnsImplementingIChangeTrackingList(DataColumn dataColumn) {
            DataColumn[] columns = columnsImplementingIChangeTracking; 
            DataColumn[] tempColumns = new DataColumn[columns.Length +1];
            columns.CopyTo(tempColumns, 0);
            tempColumns[columns.Length] = dataColumn;
            columnsImplementingIChangeTracking = tempColumns; 
        }
 
        private void RemoveColumnsImplementingIChangeTrackingList(DataColumn dataColumn) { 
            DataColumn[] columns = columnsImplementingIChangeTracking;
            DataColumn[] tempColumns = new DataColumn[columns.Length - 1]; 
            for(int i = 0, j = 0; i < columns.Length; i++) {
                if (columns[i] != dataColumn) {
                    tempColumns[j++] = columns[i];
                } 
            }
            columnsImplementingIChangeTracking = tempColumns; 
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK