DataColumnCollection.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / Data / System / Data / DataColumnCollection.cs / 6 / 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),
    ] 
#if WINFSInternalOnly 
    internal
#else 
    public
#endif
    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),
    ] 
#if WINFSInternalOnly 
    internal
#else 
    public
#endif
    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