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; ////// [ 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; ///Represents a collection of ////// objects for a . /// DataColumnCollection constructor. Used only by DataTable. /// internal DataColumnCollection(DataTable table) { this.table = table; columnFromName = new Hashtable(); } ////// 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 list of the collection items. ////// 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 at the specified index. /// /// 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; } } ///Gets the ///from the collection with the specified name. /// 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)); } ///Adds the specified ////// to the columns collection. /// public void AddRange(DataColumn[] columns) { if (table.fInitInProgress) { delayedAddRangeColumns = columns; return; } if (columns != null) { foreach(DataColumn column in columns) { if (column != null) { Add(column); } } } } ///[To be supplied.] ////// 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, type, and compute expression 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 and type to the columns collection. /// public DataColumn Add(string columnName) { DataColumn column = new DataColumn(columnName); Add(column); return column; } ///Creates and adds a ////// with the specified name to the columns collection. /// public DataColumn Add() { DataColumn column = new DataColumn(); Add(column); return column; } ///Creates and adds a ///to a columns collection. /// [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; } } ///Occurs when the columns collection changes, either by adding or removing a column. ////// 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); } } ////// 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); } } ///Checks /// if /// a given column can be removed from the collection. ////// 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); } ////// Clears the collection of any columns. /// ////// 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]; } } ///Checks whether the collection contains a column with the specified name. ////// 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 specified ///. /// /// 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; } } ///Returns the index of /// a column specified by name. ////// 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)); } ////// 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); } } ////// Raises the ///event. /// /// private void OnCollectionChanging(CollectionChangeEventArgs ccevent) { if (onCollectionChangingDelegate != null) { onCollectionChangingDelegate(this, ccevent); } } internal void OnColumnPropertyChanged(CollectionChangeEventArgs ccevent) { table.UpdatePropertyDescriptorCollectionCache(); if (onColumnPropertyChangedDelegate != null) { onColumnPropertyChangedDelegate(this, ccevent); } } ///[To be supplied.] ////// 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]); } ////// 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 specified ////// from the collection. /// public void RemoveAt(int index) { DataColumn dc = this[index]; if (dc == null) throw ExceptionBuilder.ColumnOutOfRange(index); Remove(dc); } ///Removes the /// column at the specified index from the collection. ////// public void Remove(string name) { DataColumn dc = this[name]; if (dc == null) throw ExceptionBuilder.ColumnNotInTheTable(name, table.TableName); Remove(dc); } ///Removes the /// column with the specified name from the collection. ////// 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; ////// [ 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; ///Represents a collection of ////// objects for a . /// DataColumnCollection constructor. Used only by DataTable. /// internal DataColumnCollection(DataTable table) { this.table = table; columnFromName = new Hashtable(); } ////// 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 list of the collection items. ////// 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 at the specified index. /// /// 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; } } ///Gets the ///from the collection with the specified name. /// 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)); } ///Adds the specified ////// to the columns collection. /// public void AddRange(DataColumn[] columns) { if (table.fInitInProgress) { delayedAddRangeColumns = columns; return; } if (columns != null) { foreach(DataColumn column in columns) { if (column != null) { Add(column); } } } } ///[To be supplied.] ////// 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, type, and compute expression 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 and type to the columns collection. /// public DataColumn Add(string columnName) { DataColumn column = new DataColumn(columnName); Add(column); return column; } ///Creates and adds a ////// with the specified name to the columns collection. /// public DataColumn Add() { DataColumn column = new DataColumn(); Add(column); return column; } ///Creates and adds a ///to a columns collection. /// [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; } } ///Occurs when the columns collection changes, either by adding or removing a column. ////// 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); } } ////// 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); } } ///Checks /// if /// a given column can be removed from the collection. ////// 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); } ////// Clears the collection of any columns. /// ////// 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]; } } ///Checks whether the collection contains a column with the specified name. ////// 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 specified ///. /// /// 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; } } ///Returns the index of /// a column specified by name. ////// 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)); } ////// 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); } } ////// Raises the ///event. /// /// private void OnCollectionChanging(CollectionChangeEventArgs ccevent) { if (onCollectionChangingDelegate != null) { onCollectionChangingDelegate(this, ccevent); } } internal void OnColumnPropertyChanged(CollectionChangeEventArgs ccevent) { table.UpdatePropertyDescriptorCollectionCache(); if (onColumnPropertyChangedDelegate != null) { onColumnPropertyChangedDelegate(this, ccevent); } } ///[To be supplied.] ////// 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]); } ////// 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 specified ////// from the collection. /// public void RemoveAt(int index) { DataColumn dc = this[index]; if (dc == null) throw ExceptionBuilder.ColumnOutOfRange(index); Remove(dc); } ///Removes the /// column at the specified index from the collection. ////// public void Remove(string name) { DataColumn dc = this[name]; if (dc == null) throw ExceptionBuilder.ColumnNotInTheTable(name, table.TableName); Remove(dc); } ///Removes the /// column with the specified name from the collection. ////// 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
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- HwndHostAutomationPeer.cs
- EdmValidator.cs
- DbConnectionOptions.cs
- ImageListStreamer.cs
- DynamicMethod.cs
- ObfuscationAttribute.cs
- HttpModulesSection.cs
- NativeMethods.cs
- SendActivityDesignerTheme.cs
- DataGridViewComboBoxColumnDesigner.cs
- PropertyGrid.cs
- X509Certificate2Collection.cs
- PropertyValueUIItem.cs
- DataGridHeaderBorder.cs
- FormViewDeletedEventArgs.cs
- BCryptNative.cs
- ServiceModelTimeSpanValidator.cs
- SmtpException.cs
- WmlCommandAdapter.cs
- SetIterators.cs
- GenericUI.cs
- SiteMapHierarchicalDataSourceView.cs
- OperandQuery.cs
- RemoteDebugger.cs
- D3DImage.cs
- CommandDevice.cs
- SortDescriptionCollection.cs
- ClientProtocol.cs
- NamespaceCollection.cs
- InvalidOleVariantTypeException.cs
- ScrollChrome.cs
- CompoundFileReference.cs
- StickyNoteHelper.cs
- ListViewUpdateEventArgs.cs
- sqlser.cs
- TypeElement.cs
- StaticFileHandler.cs
- CheckBoxField.cs
- CustomAttribute.cs
- BlurBitmapEffect.cs
- MarkupExtensionParser.cs
- CompiledRegexRunnerFactory.cs
- WebPartTracker.cs
- NonParentingControl.cs
- WCFModelStrings.Designer.cs
- ColorMatrix.cs
- ReadOnlyHierarchicalDataSourceView.cs
- StatusBarAutomationPeer.cs
- PrincipalPermission.cs
- RegexGroupCollection.cs
- DependencyPropertyConverter.cs
- DrawingGroup.cs
- OleDbEnumerator.cs
- SqlReferenceCollection.cs
- SmtpLoginAuthenticationModule.cs
- FixedFlowMap.cs
- RegexGroupCollection.cs
- RegexInterpreter.cs
- DigitShape.cs
- ClientFormsIdentity.cs
- ArrayEditor.cs
- GenericPrincipal.cs
- TrackingParameters.cs
- UpdateTracker.cs
- DesignerResources.cs
- RangeValidator.cs
- RequestCachingSection.cs
- CachingHintValidation.cs
- IisTraceWebEventProvider.cs
- CapabilitiesRule.cs
- ColorConverter.cs
- HtmlInputFile.cs
- SqlServices.cs
- QueryPageSettingsEventArgs.cs
- TextBlock.cs
- SystemDropShadowChrome.cs
- SmtpCommands.cs
- WebServiceData.cs
- ListBase.cs
- QilFunction.cs
- PropertyEmitterBase.cs
- CommandPlan.cs
- SimpleRecyclingCache.cs
- ServiceDebugBehavior.cs
- EntityDataSourceContainerNameItem.cs
- SmiEventSink.cs
- IOException.cs
- AsyncOperation.cs
- NetPipeSectionData.cs
- CharacterHit.cs
- ZipPackage.cs
- dataobject.cs
- DataGridViewCellContextMenuStripNeededEventArgs.cs
- GridViewSortEventArgs.cs
- COM2TypeInfoProcessor.cs
- DataGridViewCellMouseEventArgs.cs
- FixedLineResult.cs
- ListView.cs
- XslNumber.cs
- GorillaCodec.cs