Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System.Data / System / Data / DataTableCollection.cs
blobb42df0df4e19b1b09922438c328224847b6c0561
1 //------------------------------------------------------------------------------
2 // <copyright file="DataTableCollection.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 // <owner current="true" primary="false">Microsoft</owner>
7 // <owner current="false" primary="false">Microsoft</owner>
8 //------------------------------------------------------------------------------
10 namespace System.Data {
11 using System;
12 using System.Diagnostics;
13 using System.Collections;
14 using System.ComponentModel;
15 using System.Globalization;
17 /// <devdoc>
18 /// <para>
19 /// Represents the collection of tables for the <see cref='System.Data.DataSet'/>.
20 /// </para>
21 /// </devdoc>
23 DefaultEvent("CollectionChanged"),
24 Editor("Microsoft.VSDesigner.Data.Design.TablesCollectionEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing),
25 ListBindable(false),
27 public sealed class DataTableCollection : InternalDataCollectionBase {
29 private readonly DataSet dataSet = null;
30 // private DataTable[] tables = new DataTable[2];
31 // private int tableCount = 0;
32 private readonly ArrayList _list = new ArrayList();
33 private int defaultNameIndex = 1;
34 private DataTable[] delayedAddRangeTables = null;
36 private CollectionChangeEventHandler onCollectionChangedDelegate = null;
37 private CollectionChangeEventHandler onCollectionChangingDelegate = null;
39 private static int _objectTypeCount; // Bid counter
40 private readonly int _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount);
42 /// <devdoc>
43 /// DataTableCollection constructor. Used only by DataSet.
44 /// </devdoc>
45 internal DataTableCollection(DataSet dataSet) {
46 Bid.Trace("<ds.DataTableCollection.DataTableCollection|INFO> %d#, dataSet=%d\n", ObjectID, (dataSet != null) ? dataSet.ObjectID : 0);
47 this.dataSet = dataSet;
50 /// <devdoc>
51 /// <para>
52 /// Gets the tables
53 /// in the collection as an object.
54 /// </para>
55 /// </devdoc>
56 protected override ArrayList List {
57 get {
58 return _list;
62 internal int ObjectID {
63 get {
64 return _objectID;
68 /// <devdoc>
69 /// <para>Gets the table specified by its index.</para>
70 /// </devdoc>
71 public DataTable this[int index] {
72 get {
73 try { // Perf: use the readonly _list field directly and let ArrayList check the range
74 return(DataTable) _list[index];
76 catch(ArgumentOutOfRangeException) {
77 throw ExceptionBuilder.TableOutOfRange(index);
82 /// <devdoc>
83 /// <para>Gets the table in the collection with the given name (not case-sensitive).</para>
84 /// </devdoc>
85 public DataTable this[string name] {
86 get {
87 int index = InternalIndexOf(name);
88 if (index == -2) {
89 throw ExceptionBuilder.CaseInsensitiveNameConflict(name);
91 if (index == -3) {
92 throw ExceptionBuilder.NamespaceNameConflict(name);
94 return (index < 0) ? null : (DataTable)_list[index];
98 public DataTable this[string name, string tableNamespace] {
99 get {
100 if (tableNamespace == null)
101 throw ExceptionBuilder.ArgumentNull("tableNamespace");
102 int index = InternalIndexOf(name, tableNamespace);
103 if (index == -2) {
104 throw ExceptionBuilder.CaseInsensitiveNameConflict(name);
106 return (index < 0) ? null : (DataTable)_list[index];
110 // Case-sensitive search in Schema, data and diffgram loading
111 internal DataTable GetTable(string name, string ns)
113 for (int i = 0; i < _list.Count; i++) {
114 DataTable table = (DataTable) _list[i];
115 if (table.TableName == name && table.Namespace == ns)
116 return table;
118 return null;
121 // Case-sensitive smart search: it will look for a table using the ns only if required to
122 // resolve a conflict
123 internal DataTable GetTableSmart(string name, string ns){
124 int fCount = 0;
125 DataTable fTable = null;
126 for (int i = 0; i < _list.Count; i++) {
127 DataTable table = (DataTable) _list[i];
128 if (table.TableName == name) {
129 if (table.Namespace == ns)
130 return table;
131 fCount++;
132 fTable = table;
135 // if we get here we didn't match the namespace
136 // so return the table only if fCount==1 (it's the only one)
137 return (fCount == 1) ? fTable : null;
139 /// <devdoc>
140 /// <para>
141 /// Adds
142 /// the specified table to the collection.
143 /// </para>
144 /// </devdoc>
145 public void Add(DataTable table) {
146 IntPtr hscp;
147 Bid.ScopeEnter(out hscp, "<ds.DataTableCollection.Add|API> %d#, table=%d\n", ObjectID, (table!= null) ? table.ObjectID : 0);
148 try {
149 OnCollectionChanging(new CollectionChangeEventArgs(CollectionChangeAction.Add, table));
150 BaseAdd(table);
151 ArrayAdd(table);
153 if (table.SetLocaleValue(dataSet.Locale, false, false) ||
154 table.SetCaseSensitiveValue(dataSet.CaseSensitive, false, false)) {
155 table.ResetIndexes();
157 OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Add, table));
159 finally {
160 Bid.ScopeLeave(ref hscp);
164 /// <devdoc>
165 /// <para>[To be supplied.]</para>
166 /// </devdoc>
167 public void AddRange(DataTable[] tables) {
168 IntPtr hscp;
169 Bid.ScopeEnter(out hscp, "<ds.DataTableCollection.AddRange|API> %d#\n", ObjectID);
170 try {
171 if (dataSet.fInitInProgress) {
172 delayedAddRangeTables = tables;
173 return;
176 if (tables != null) {
177 foreach(DataTable table in tables) {
178 if (table != null) {
179 Add(table);
184 finally{
185 Bid.ScopeLeave(ref hscp);
189 /// <devdoc>
190 /// <para>
191 /// Creates a table with the given name and adds it to the
192 /// collection.
193 /// </para>
194 /// </devdoc>
195 public DataTable Add(string name) {
196 DataTable table = new DataTable(name);
197 // fxcop: new DataTable should inherit the CaseSensitive, Locale, Namespace from DataSet
198 Add(table);
199 return table;
202 public DataTable Add(string name, string tableNamespace) {
203 DataTable table = new DataTable(name, tableNamespace);
204 // fxcop: new DataTable should inherit the CaseSensitive, Locale from DataSet
205 Add(table);
206 return table;
208 /// <devdoc>
209 /// <para>
210 /// Creates a new table with a default name and adds it to
211 /// the collection.
212 /// </para>
213 /// </devdoc>
214 public DataTable Add() {
215 DataTable table = new DataTable();
216 // fxcop: new DataTable should inherit the CaseSensitive, Locale, Namespace from DataSet
217 Add(table);
218 return table;
221 /// <devdoc>
222 /// <para>
223 /// Occurs when the collection is changed.
224 /// </para>
225 /// </devdoc>
226 [ResDescriptionAttribute(Res.collectionChangedEventDescr)]
227 public event CollectionChangeEventHandler CollectionChanged {
228 add {
229 Bid.Trace("<ds.DataTableCollection.add_CollectionChanged|API> %d#\n", ObjectID);
230 onCollectionChangedDelegate += value;
232 remove {
233 Bid.Trace("<ds.DataTableCollection.remove_CollectionChanged|API> %d#\n", ObjectID);
234 onCollectionChangedDelegate -= value;
238 /// <devdoc>
239 /// <para>[To be supplied.]</para>
240 /// </devdoc>
241 public event CollectionChangeEventHandler CollectionChanging {
242 add {
243 Bid.Trace("<ds.DataTableCollection.add_CollectionChanging|API> %d#\n", ObjectID);
244 onCollectionChangingDelegate += value;
246 remove {
247 Bid.Trace("<ds.DataTableCollection.remove_CollectionChanging|API> %d#\n", ObjectID);
248 onCollectionChangingDelegate -= value;
252 /// <devdoc>
253 /// Adds the table to the tables array.
254 /// </devdoc>
255 private void ArrayAdd(DataTable table) {
256 _list.Add(table);
259 /// <devdoc>
260 /// Creates a new default name.
261 /// </devdoc>
262 internal string AssignName() {
263 string newName = null;
264 // RAIDBUG: 91671
265 while(this.Contains( newName = MakeName(defaultNameIndex)))
266 defaultNameIndex++;
267 return newName;
270 /// <devdoc>
271 /// Does verification on the table and it's name, and points the table at the dataSet that owns this collection.
272 /// An ArgumentNullException is thrown if this table is null. An ArgumentException is thrown if this table
273 /// already belongs to this collection, belongs to another collection.
274 /// A DuplicateNameException is thrown if this collection already has a table with the same
275 /// name (case insensitive).
276 /// </devdoc>
277 private void BaseAdd(DataTable table) {
278 if (table == null)
279 throw ExceptionBuilder.ArgumentNull("table");
280 if (table.DataSet == dataSet)
281 throw ExceptionBuilder.TableAlreadyInTheDataSet();
282 if (table.DataSet != null)
283 throw ExceptionBuilder.TableAlreadyInOtherDataSet();
285 if (table.TableName.Length == 0)
286 table.TableName = AssignName();
287 else {
288 if (NamesEqual(table.TableName, dataSet.DataSetName, false, dataSet.Locale) != 0 && !table.fNestedInDataset)
289 throw ExceptionBuilder.DatasetConflictingName(dataSet.DataSetName);
290 RegisterName(table.TableName, table.Namespace);
293 table.SetDataSet(dataSet);
295 //must run thru the document incorporating the addition of this data table
296 //must make sure there is no other schema component which have the same
297 // identity as this table (for example, there must not be a table with the
298 // same identity as a column in this schema.
301 /// <devdoc>
302 /// BaseGroupSwitch will intelligently remove and add tables from the collection.
303 /// </devdoc>
304 private void BaseGroupSwitch(DataTable[] oldArray, int oldLength, DataTable[] newArray, int newLength) {
305 // We're doing a smart diff of oldArray and newArray to find out what
306 // should be removed. We'll pass through oldArray and see if it exists
307 // in newArray, and if not, do remove work. newBase is an opt. in case
308 // the arrays have similar prefixes.
309 int newBase = 0;
310 for (int oldCur = 0; oldCur < oldLength; oldCur++) {
311 bool found = false;
312 for (int newCur = newBase; newCur < newLength; newCur++) {
313 if (oldArray[oldCur] == newArray[newCur]) {
314 if (newBase == newCur) {
315 newBase++;
317 found = true;
318 break;
321 if (!found) {
322 // This means it's in oldArray and not newArray. Remove it.
323 if (oldArray[oldCur].DataSet == dataSet) {
324 BaseRemove(oldArray[oldCur]);
329 // Now, let's pass through news and those that don't belong, add them.
330 for (int newCur = 0; newCur < newLength; newCur++) {
331 if (newArray[newCur].DataSet != dataSet) {
332 BaseAdd(newArray[newCur]);
333 _list.Add(newArray[newCur]);
338 /// <devdoc>
339 /// Does verification on the table and it's name, and clears the table's dataSet pointer.
340 /// An ArgumentNullException is thrown if this table is null. An ArgumentException is thrown
341 /// if this table doesn't belong to this collection or if this table is part of a relationship.
342 /// </devdoc>
343 private void BaseRemove(DataTable table) {
344 if (CanRemove(table, true)) {
345 UnregisterName(table.TableName);
346 table.SetDataSet(null);
349 _list.Remove(table);
350 dataSet.OnRemovedTable(table);
353 /// <devdoc>
354 /// <para>
355 /// Verifies if a given table can be removed from the collection.
356 /// </para>
357 /// </devdoc>
358 public bool CanRemove(DataTable table) {
359 return CanRemove(table, false);
362 internal bool CanRemove(DataTable table, bool fThrowException) {
363 IntPtr hscp;
364 Bid.ScopeEnter(out hscp, "<ds.DataTableCollection.CanRemove|INFO> %d#, table=%d, fThrowException=%d{bool}\n", ObjectID, (table != null)? table.ObjectID : 0 , fThrowException);
365 try {
366 if (table == null) {
367 if (!fThrowException)
368 return false;
369 else
370 throw ExceptionBuilder.ArgumentNull("table");
372 if (table.DataSet != dataSet) {
373 if (!fThrowException)
374 return false;
375 else
376 throw ExceptionBuilder.TableNotInTheDataSet(table.TableName);
379 // allow subclasses to throw.
380 dataSet.OnRemoveTable(table);
382 if (table.ChildRelations.Count != 0 || table.ParentRelations.Count != 0) {
383 if (!fThrowException)
384 return false;
385 else
386 throw ExceptionBuilder.TableInRelation();
389 for (ParentForeignKeyConstraintEnumerator constraints = new ParentForeignKeyConstraintEnumerator(dataSet, table); constraints.GetNext();) {
390 ForeignKeyConstraint constraint = constraints.GetForeignKeyConstraint();
391 if (constraint.Table == table && constraint.RelatedTable == table) // we can go with (constraint.Table == constraint.RelatedTable)
392 continue;
393 if (!fThrowException)
394 return false;
395 else
396 throw ExceptionBuilder.TableInConstraint(table, constraint);
399 for (ChildForeignKeyConstraintEnumerator constraints = new ChildForeignKeyConstraintEnumerator(dataSet, table); constraints.GetNext();) {
400 ForeignKeyConstraint constraint = constraints.GetForeignKeyConstraint();
401 if (constraint.Table == table && constraint.RelatedTable == table) // bug 97670
402 continue;
404 if (!fThrowException)
405 return false;
406 else
407 throw ExceptionBuilder.TableInConstraint(table, constraint);
410 return true;
412 finally{
413 Bid.ScopeLeave(ref hscp);
417 /// <devdoc>
418 /// <para>
419 /// Clears the collection of any tables.
420 /// </para>
421 /// </devdoc>
422 public void Clear() {
423 IntPtr hscp;
424 Bid.ScopeEnter(out hscp, "<ds.DataTableCollection.Clear|API> %d#\n", ObjectID);
425 try {
426 int oldLength = _list.Count;
427 DataTable[] tables = new DataTable[_list.Count];
428 _list.CopyTo(tables, 0);
430 OnCollectionChanging(RefreshEventArgs);
432 if (dataSet.fInitInProgress && delayedAddRangeTables != null) {
433 delayedAddRangeTables = null;
436 BaseGroupSwitch(tables, oldLength, null, 0);
437 _list.Clear();
439 OnCollectionChanged(RefreshEventArgs);
441 finally {
442 Bid.ScopeLeave(ref hscp);
446 /// <devdoc>
447 /// <para>
448 /// Checks if a table, specified by name, exists in the collection.
449 /// </para>
450 /// </devdoc>
451 public bool Contains(string name) {
452 return (InternalIndexOf(name) >= 0);
455 public bool Contains(string name, string tableNamespace) {
456 if (name == null)
457 throw ExceptionBuilder.ArgumentNull("name");
459 if (tableNamespace == null)
460 throw ExceptionBuilder.ArgumentNull("tableNamespace");
462 return (InternalIndexOf(name, tableNamespace) >= 0);
465 internal bool Contains(string name, string tableNamespace, bool checkProperty, bool caseSensitive) {
466 if (!caseSensitive)
467 return (InternalIndexOf(name) >= 0);
469 // Case-Sensitive compare
470 int count = _list.Count;
471 for (int i = 0; i < count; i++) {
472 DataTable table = (DataTable) _list[i];
473 // this may be needed to check wether the cascading is creating some conflicts
474 string ns = checkProperty ? table.Namespace : table.tableNamespace ;
475 if (NamesEqual(table.TableName, name, true, dataSet.Locale) == 1 && (ns == tableNamespace))
476 return true;
478 return false;
481 internal bool Contains(string name, bool caseSensitive) {
482 if (!caseSensitive)
483 return (InternalIndexOf(name) >= 0);
485 // Case-Sensitive compare
486 int count = _list.Count;
487 for (int i = 0; i < count; i++) {
488 DataTable table = (DataTable) _list[i];
489 if (NamesEqual(table.TableName, name, true, dataSet.Locale) == 1 )
490 return true;
492 return false;
495 public void CopyTo(DataTable[] array, int index) {
496 if (array==null)
497 throw ExceptionBuilder.ArgumentNull("array");
498 if (index < 0)
499 throw ExceptionBuilder.ArgumentOutOfRange("index");
500 if (array.Length - index < _list.Count)
501 throw ExceptionBuilder.InvalidOffsetLength();
502 for(int i = 0; i < _list.Count; ++i) {
503 array[index + i] = (DataTable)_list[i];
507 /// <devdoc>
508 /// <para>
509 /// Returns the index of a specified <see cref='System.Data.DataTable'/>.
510 /// </para>
511 /// </devdoc>
512 public int IndexOf(DataTable table) {
513 int tableCount = _list.Count;
514 for (int i = 0; i < tableCount; ++i) {
515 if (table == (DataTable) _list[i]) {
516 return i;
519 return -1;
522 /// <devdoc>
523 /// <para>
524 /// Returns the index of the
525 /// table with the given name (case insensitive), or -1 if the table
526 /// doesn't exist in the collection.
527 /// </para>
528 /// </devdoc>
529 public int IndexOf(string tableName) {
530 int index = InternalIndexOf(tableName);
531 return (index < 0) ? -1 : index;
534 public int IndexOf(string tableName, string tableNamespace) {
535 return IndexOf( tableName, tableNamespace, true);
538 internal int IndexOf(string tableName, string tableNamespace, bool chekforNull) { // this should be public! why it is missing?
539 if (chekforNull) {
540 if (tableName == null)
541 throw ExceptionBuilder.ArgumentNull("tableName");
542 if (tableNamespace == null)
543 throw ExceptionBuilder.ArgumentNull("tableNamespace");
545 int index = InternalIndexOf(tableName, tableNamespace);
546 return (index < 0) ? -1 : index;
549 internal void ReplaceFromInference(System.Collections.Generic.List<DataTable> tableList) {
550 Debug.Assert(_list.Count == tableList.Count, "Both lists should have equal numbers of tables");
551 _list.Clear();
552 _list.AddRange(tableList);
555 // Return value:
556 // >= 0: find the match
557 // -1: No match
558 // -2: At least two matches with different cases
559 // -3: At least two matches with different namespaces
560 internal int InternalIndexOf(string tableName) {
561 int cachedI = -1;
562 if ((null != tableName) && (0 < tableName.Length)) {
563 int count = _list.Count;
564 int result = 0;
565 for (int i = 0; i < count; i++) {
566 DataTable table = (DataTable) _list[i];
567 result = NamesEqual(table.TableName, tableName, false, dataSet.Locale);
568 if (result == 1) {
569 // ok, we have found a table with the same name.
570 // let's see if there are any others with the same name
571 // if any let's return (-3) otherwise...
572 for (int j=i+1;j<count;j++) {
573 DataTable dupTable = (DataTable) _list[j];
574 if (NamesEqual(dupTable.TableName, tableName, false, dataSet.Locale) == 1)
575 return -3;
577 //... let's just return i
578 return i;
581 if (result == -1)
582 cachedI = (cachedI == -1) ? i : -2;
585 return cachedI;
588 // Return value:
589 // >= 0: find the match
590 // -1: No match
591 // -2: At least two matches with different cases
592 internal int InternalIndexOf(string tableName, string tableNamespace) {
593 int cachedI = -1;
594 if ((null != tableName) && (0 < tableName.Length)) {
595 int count = _list.Count;
596 int result = 0;
597 for (int i = 0; i < count; i++) {
598 DataTable table = (DataTable) _list[i];
599 result = NamesEqual(table.TableName, tableName, false, dataSet.Locale);
600 if ((result == 1) && (table.Namespace == tableNamespace))
601 return i;
603 if ((result == -1) && (table.Namespace == tableNamespace))
604 cachedI = (cachedI == -1) ? i : -2;
607 return cachedI;
611 internal void FinishInitCollection() {
612 if (delayedAddRangeTables != null) {
613 foreach(DataTable table in delayedAddRangeTables) {
614 if (table != null) {
615 Add(table);
618 delayedAddRangeTables = null;
622 /// <devdoc>
623 /// Makes a default name with the given index. e.g. Table1, Table2, ... Tablei
624 /// </devdoc>
625 private string MakeName(int index) {
626 if (1 == index) {
627 return "Table1";
629 return "Table" + index.ToString(System.Globalization.CultureInfo.InvariantCulture);
632 /// <devdoc>
633 /// <para>
634 /// Raises the <see cref='System.Data.DataTableCollection.OnCollectionChanged'/> event.
635 /// </para>
636 /// </devdoc>
637 private void OnCollectionChanged(CollectionChangeEventArgs ccevent) {
638 if (onCollectionChangedDelegate != null) {
639 Bid.Trace("<ds.DataTableCollection.OnCollectionChanged|INFO> %d#\n", ObjectID);
640 onCollectionChangedDelegate(this, ccevent);
644 /// <devdoc>
645 /// <para>[To be supplied.]</para>
646 /// </devdoc>
647 private void OnCollectionChanging(CollectionChangeEventArgs ccevent) {
648 if (onCollectionChangingDelegate != null) {
649 Bid.Trace("<ds.DataTableCollection.OnCollectionChanging|INFO> %d#\n", ObjectID);
650 onCollectionChangingDelegate(this, ccevent);
654 /// <devdoc>
655 /// Registers this name as being used in the collection. Will throw an ArgumentException
656 /// if the name is already being used. Called by Add, All property, and Table.TableName property.
657 /// if the name is equivalent to the next default name to hand out, we increment our defaultNameIndex.
658 /// </devdoc>
659 internal void RegisterName(string name, string tbNamespace) {
660 Bid.Trace("<ds.DataTableCollection.RegisterName|INFO> %d#, name='%ls', tbNamespace='%ls'\n", ObjectID, name, tbNamespace);
661 Debug.Assert (name != null);
663 CultureInfo locale = dataSet.Locale;
664 int tableCount = _list.Count;
665 for (int i = 0; i < tableCount; i++) {
666 DataTable table = (DataTable) _list[i];
667 if (NamesEqual(name, table.TableName, true, locale) != 0 && (tbNamespace == table.Namespace)) {
668 throw ExceptionBuilder.DuplicateTableName(((DataTable) _list[i]).TableName);
671 if (NamesEqual(name, MakeName(defaultNameIndex), true, locale) != 0) {
672 defaultNameIndex++;
676 /// <devdoc>
677 /// <para>
678 /// Removes the specified table from the collection.
679 /// </para>
680 /// </devdoc>
681 public void Remove(DataTable table) {
682 IntPtr hscp;
683 Bid.ScopeEnter(out hscp, "<ds.DataTableCollection.Remove|API> %d#, table=%d\n", ObjectID, (table != null) ? table.ObjectID : 0);
684 try {
685 OnCollectionChanging(new CollectionChangeEventArgs(CollectionChangeAction.Remove, table));
686 BaseRemove(table);
687 OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Remove, table));
689 finally{
690 Bid.ScopeLeave(ref hscp);
694 /// <devdoc>
695 /// <para>
696 /// Removes the
697 /// table at the given index from the collection
698 /// </para>
699 /// </devdoc>
700 public void RemoveAt(int index) {
701 IntPtr hscp;
702 Bid.ScopeEnter(out hscp, "<ds.DataTableCollection.RemoveAt|API> %d#, index=%d\n", ObjectID, index);
703 try {
704 DataTable dt = this[index];
705 if (dt == null)
706 throw ExceptionBuilder.TableOutOfRange(index);
707 Remove(dt);
709 finally {
710 Bid.ScopeLeave(ref hscp);
714 /// <devdoc>
715 /// <para>
716 /// Removes the table with a specified name from the
717 /// collection.
718 /// </para>
719 /// </devdoc>
720 public void Remove(string name) {
721 IntPtr hscp;
722 Bid.ScopeEnter(out hscp, "<ds.DataTableCollection.Remove|API> %d#, name='%ls'\n", ObjectID, name);
723 try {
724 DataTable dt = this[name];
725 if (dt == null)
726 throw ExceptionBuilder.TableNotInTheDataSet(name);
727 Remove(dt);
729 finally{
730 Bid.ScopeLeave(ref hscp);
734 public void Remove(string name, string tableNamespace) {
735 if (name == null)
736 throw ExceptionBuilder.ArgumentNull("name");
737 if (tableNamespace == null)
738 throw ExceptionBuilder.ArgumentNull("tableNamespace");
739 DataTable dt = this[name, tableNamespace];
740 if (dt == null)
741 throw ExceptionBuilder.TableNotInTheDataSet(name);
742 Remove(dt);
746 /// <devdoc>
747 /// Unregisters this name as no longer being used in the collection. Called by Remove, All property, and
748 /// Table.TableName property. If the name is equivalent to the last proposed default name, we walk backwards
749 /// to find the next proper default name to use.
750 /// </devdoc>
751 internal void UnregisterName(string name) {
752 Bid.Trace("<ds.DataTableCollection.UnregisterName|INFO> %d#, name='%ls'\n", ObjectID, name);
753 if (NamesEqual(name, MakeName(defaultNameIndex - 1), true, dataSet.Locale) != 0) {
754 do {
755 defaultNameIndex--;
756 } while (defaultNameIndex > 1 &&
757 !Contains(MakeName(defaultNameIndex - 1)));