| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856 |
- //------------------------------------------------------------------------------
- // <copyright file="DataColumnCollection.cs" company="Microsoft">
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- // <owner current="true" primary="true">[....]</owner>
- // <owner current="true" primary="false">[....]</owner>
- // <owner current="false" primary="false">[....]</owner>
- //------------------------------------------------------------------------------
- namespace System.Data {
- using System;
- using System.Xml;
- using System.Collections;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data.Common;
- using System.Diagnostics;
- /// <devdoc>
- /// <para>Represents a collection of <see cref='System.Data.DataColumn'/>
- /// objects for a <see cref='System.Data.DataTable'/>.</para>
- /// </devdoc>
- [
- DefaultEvent("CollectionChanged"),
- Editor("Microsoft.VSDesigner.Data.Design.ColumnsCollectionEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing),
- ]
- public sealed class DataColumnCollection : InternalDataCollectionBase {
- private readonly DataTable table;
- private readonly ArrayList _list = new ArrayList();
- private int defaultNameIndex = 1;
- private DataColumn[] delayedAddRangeColumns;
- private readonly Dictionary<string, DataColumn> columnFromName; // Links names to columns
- 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;
- /// <devdoc>
- /// DataColumnCollection constructor. Used only by DataTable.
- /// </devdoc>
- internal DataColumnCollection(DataTable table) {
- this.table = table;
- columnFromName = new Dictionary<string, DataColumn>();
- }
- /// <devdoc>
- /// <para>Gets the list of the collection items.</para>
- /// </devdoc>
- 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;
- }
- }
- /// <devdoc>
- /// <para>
- /// Gets the <see cref='System.Data.DataColumn'/>
- /// from the collection at the specified index.
- /// </para>
- /// </devdoc>
- 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);
- }
- }
- }
- /// <devdoc>
- /// <para>Gets the <see cref='System.Data.DataColumn'/> from the collection with the specified name.</para>
- /// </devdoc>
- public DataColumn this[string name] {
- get {
- if (null == name) {
- throw ExceptionBuilder.ArgumentNull("name");
- }
- DataColumn column;
- if ((!columnFromName.TryGetValue(name, out column)) || (column == null)) {
- // 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;
- if ((columnFromName.TryGetValue(name, out column)) && (column != null) && (column.Namespace == ns)) {
- return column;
- }
- return null;
- }
- }
- internal void EnsureAdditionalCapacity(int capacity) {
- if (_list.Capacity < capacity + _list.Count) {
- _list.Capacity = capacity + _list.Count;
- }
- }
- /// <devdoc>
- /// <para>Adds the specified <see cref='System.Data.DataColumn'/>
- /// to the columns collection.</para>
- /// </devdoc>
- 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));
- }
- /// <devdoc>
- /// <para>[To be supplied.]</para>
- /// </devdoc>
- public void AddRange(DataColumn[] columns) {
- if (table.fInitInProgress) {
- delayedAddRangeColumns = columns;
- return;
- }
- if (columns != null) {
- foreach(DataColumn column in columns) {
- if (column != null) {
- Add(column);
- }
- }
- }
- }
- /// <devdoc>
- /// <para>Creates and adds a <see cref='System.Data.DataColumn'/>
- /// with
- /// the specified name, type, and compute expression to the columns collection.</para>
- /// </devdoc>
- public DataColumn Add(string columnName, Type type, string expression) {
- DataColumn column = new DataColumn(columnName, type, expression);
- Add(column);
- return column;
- }
- /// <devdoc>
- /// <para>Creates and adds a <see cref='System.Data.DataColumn'/>
- /// with the
- /// specified name and type to the columns collection.</para>
- /// </devdoc>
- public DataColumn Add(string columnName, Type type) {
- DataColumn column = new DataColumn(columnName, type);
- Add(column);
- return column;
- }
- /// <devdoc>
- /// <para>Creates and adds a <see cref='System.Data.DataColumn'/>
- /// with the specified name to the columns collection.</para>
- /// </devdoc>
- public DataColumn Add(string columnName) {
- DataColumn column = new DataColumn(columnName);
- Add(column);
- return column;
- }
- /// <devdoc>
- /// <para>Creates and adds a <see cref='System.Data.DataColumn'/> to a columns collection.</para>
- /// </devdoc>
- public DataColumn Add() {
- DataColumn column = new DataColumn();
- Add(column);
- return column;
- }
- /// <devdoc>
- /// <para>Occurs when the columns collection changes, either by adding or removing a column.</para>
- /// </devdoc>
- [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;
- }
- }
- /// <devdoc>
- /// Adds the column to the columns array.
- /// </devdoc>
- 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);
- }
- }
- /// <devdoc>
- /// Creates a new default name.
- /// </devdoc>
- internal string AssignName() {
- string newName = MakeName(defaultNameIndex++);
- while (columnFromName.ContainsKey(newName)) {
- newName = MakeName(defaultNameIndex++);
- }
- return newName;
- }
- /// <devdoc>
- /// 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).
- /// </devdoc>
- 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);
- 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;
- }
- }
- /// <devdoc>
- /// BaseGroupSwitch will intelligently remove and add tables from the collection.
- /// </devdoc>
- 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);
- }
- }
- /// <devdoc>
- /// 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.
- /// </devdoc>
- 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);
- }
- }
- /// <devdoc>
- /// <para>Checks
- /// if
- /// a given column can be removed from the collection.</para>
- /// </devdoc>
- 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);
- }
- }
- /// <devdoc>
- /// <para>
- /// Clears the collection of any columns.
- /// </para>
- /// </devdoc>
- 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);
- }
- /// <devdoc>
- /// <para>Checks whether the collection contains a column with the specified name.</para>
- /// </devdoc>
- public bool Contains(string name) {
- DataColumn column;
- if ((columnFromName.TryGetValue(name, out column)) && (column != null)) {
- return true;
- }
- return (IndexOfCaseInsensitive(name) >= 0);
- }
- internal bool Contains(string name, bool caseSensitive) {
- DataColumn column;
- if ((columnFromName.TryGetValue(name, out column)) && (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];
- }
- }
- /// <devdoc>
- /// <para>
- /// Returns the index of a specified <see cref='System.Data.DataColumn'/>.
- /// </para>
- /// </devdoc>
- 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;
- }
- /// <devdoc>
- /// <para>Returns the index of
- /// a column specified by name.</para>
- /// </devdoc>
- public int IndexOf(string columnName) {
- if ((null != columnName) && (0 < columnName.Length)) {
- int count = Count;
- DataColumn column;
- if ((columnFromName.TryGetValue(columnName, out column)) && (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;
- }
- }
- /// <devdoc>
- /// Makes a default name with the given index. e.g. Column1, Column2, ... Columni
- /// </devdoc>
- 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));
- }
- /// <devdoc>
- /// <para>
- /// Raises the <see cref='System.Data.DataColumnCollection.OnCollectionChanged'/> event.
- /// </para>
- /// </devdoc>
- 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);
- }
- }
- /// <devdoc>
- /// <para>[To be supplied.]</para>
- /// </devdoc>
- private void OnCollectionChanging(CollectionChangeEventArgs ccevent) {
- if (onCollectionChangingDelegate != null) {
- onCollectionChangingDelegate(this, ccevent);
- }
- }
- internal void OnColumnPropertyChanged(CollectionChangeEventArgs ccevent) {
- table.UpdatePropertyDescriptorCollectionCache();
- if (onColumnPropertyChangedDelegate != null) {
- onColumnPropertyChangedDelegate(this, ccevent);
- }
- }
- /// <devdoc>
- /// 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.
- /// NOTE: To add a child table, pass column as null
- /// </devdoc>
- internal void RegisterColumnName(string name, DataColumn column) {
- Debug.Assert (name != null);
- try {
- columnFromName.Add(name, column);
- if (null != column) {
- column._hashCode = table.GetSpecialHashCode(name);
- }
- }
- catch (ArgumentException) { // Argument exception means that there is already an existing key
- if (columnFromName[name] != null) {
- if (column != null) {
- throw ExceptionBuilder.CannotAddDuplicate(name);
- }
- else {
- throw ExceptionBuilder.CannotAddDuplicate3(name);
- }
- }
- throw ExceptionBuilder.CannotAddDuplicate2(name);
- }
- // If we're adding a child table, then update defaultNameIndex to avoid colisions between the child table and auto-generated column names
- if ((column == null) && NamesEqual(name, MakeName(defaultNameIndex), true, table.Locale) != 0) {
- do {
- defaultNameIndex++;
- } while (Contains(MakeName(defaultNameIndex)));
- }
- }
- internal bool CanRegisterName(string name) {
- Debug.Assert (name != null, "Must specify a name");
- return (!columnFromName.ContainsKey(name));
- }
- /// <devdoc>
- /// <para>Removes the specified <see cref='System.Data.DataColumn'/>
- /// from the collection.</para>
- /// </devdoc>
- 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 --;
- }
- /// <devdoc>
- /// <para>Removes the
- /// column at the specified index from the collection.</para>
- /// </devdoc>
- public void RemoveAt(int index) {
- DataColumn dc = this[index];
- if (dc == null)
- throw ExceptionBuilder.ColumnOutOfRange(index);
- Remove(dc);
- }
- /// <devdoc>
- /// <para>Removes the
- /// column with the specified name from the collection.</para>
- /// </devdoc>
- public void Remove(string name) {
- DataColumn dc = this[name];
- if (dc == null)
- throw ExceptionBuilder.ColumnNotInTheTable(name, table.TableName);
- Remove(dc);
- }
- /// <devdoc>
- /// 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 name, we walk backwards
- /// to find the next proper default name to use.
- /// </devdoc>
- internal void UnregisterName(string name) {
- columnFromName.Remove(name);
- 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;
- }
- }
- }
|