2 // System.Data.DataTableCollection.cs
5 // Christopher Podurgiel (cpodurgiel@msn.com)
6 // Tim Coleman <tim@timcoleman.com>
9 // (C) Copyright 2002 Tim Coleman
13 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System.Collections;
37 using System.ComponentModel;
38 using System.Globalization;
43 /// Represents the collection of tables for the DataSet.
45 [Editor ("Microsoft.VSDesigner.Data.Design.TablesCollectionEditor, " + Consts.AssemblyMicrosoft_VSDesigner,
46 "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
47 [DefaultEvent ("CollectionChanged")]
48 [ListBindable (false)]
56 class DataTableCollection : InternalDataCollectionBase {
58 DataTable[] mostRecentTables;
62 internal DataTableCollection (DataSet dataSet)
65 this.dataSet = dataSet;
72 public DataTable this [int index] {
74 if (index < 0 || index >= List.Count)
75 throw new IndexOutOfRangeException (String.Format ("Cannot find table {0}", index));
76 return (DataTable)(List [index]);
80 public DataTable this [string name] {
82 int index = IndexOf (name, true);
83 return index < 0 ? null : (DataTable) List [index];
88 public DataTable this [string name, string tbNamespace] {
90 int index = IndexOf (name, tbNamespace, true);
91 return index < 0 ? null : (DataTable) List [index];
96 protected override ArrayList List {
97 get { return base.List; }
110 DataTable Table = new DataTable ();
119 void Add (DataTable table)
121 OnCollectionChanging (new CollectionChangeEventArgs (CollectionChangeAction.Add, table));
122 // check if the reference is a null reference
124 throw new ArgumentNullException ("table");
126 // check if the list already contains this tabe.
127 if (List.Contains (table))
128 throw new ArgumentException ("DataTable already belongs to this DataSet.");
130 // check if table is part of another DataSet
131 if (table.DataSet != null && table.DataSet != this.dataSet)
132 throw new ArgumentException ("DataTable already belongs to another DataSet");
134 // if the table name is null or empty string.
136 if (table.TableName == null || table.TableName == string.Empty)
139 // check if the collection has a table with the same name.
141 int tmp = IndexOf (table.TableName);
143 int tmp = IndexOf (table.TableName, table.Namespace);
145 // if we found a table with same name we have to check
146 // that it is the same case.
147 // indexof can return a table with different case letters.
149 table.TableName == this [tmp].TableName)
150 throw new DuplicateNameException ("A DataTable named '" + table.TableName + "' already belongs to this DataSet.");
153 table.dataSet = dataSet;
154 OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, table));
161 DataTable Add (string name)
163 DataTable table = new DataTable (name);
169 public DataTable Add (string name, string tbNamespace)
171 DataTable table = new DataTable (name, tbNamespace);
177 public void AddRange (DataTable [] tables)
179 if (dataSet != null && dataSet.InitInProgress) {
180 mostRecentTables = tables;
187 foreach (DataTable table in tables) {
194 internal void PostAddRange ()
196 if (mostRecentTables == null)
199 foreach (DataTable table in mostRecentTables){
204 mostRecentTables = null;
207 public bool CanRemove (DataTable table)
209 return CanRemove (table, false);
217 public bool Contains (string name)
219 return (-1 != IndexOf (name, false));
223 public bool Contains (string name, string tableNamespace)
225 return (IndexOf (name, tableNamespace) != -1);
228 public void CopyTo (DataTable [] array, int index)
230 CopyTo ((Array) array, index);
238 int IndexOf (DataTable table)
240 return List.IndexOf (table);
247 int IndexOf (string tableName)
249 return IndexOf (tableName, false);
253 public int IndexOf (string tableName, string tableNamespace)
255 if (tableNamespace == null)
256 throw new ArgumentNullException ("'tableNamespace' argument cannot be null.",
258 return IndexOf (tableName, tableNamespace, false);
262 public void Remove (DataTable table)
264 OnCollectionChanging (new CollectionChangeEventArgs (CollectionChangeAction.Remove, table));
265 if (CanRemove (table, true))
266 table.dataSet = null;
269 table.dataSet = null;
270 OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, table));
273 public void Remove (string name)
275 int index = IndexOf (name, false);
277 throw new ArgumentException ("Table " + name + " does not belong to this DataSet");
282 public void Remove (string name, string tableNamespace)
284 int index = IndexOf (name, tableNamespace, true);
286 throw new ArgumentException ("Table " + name + " does not belong to this DataSet");
292 public void RemoveAt (int index)
294 Remove (this [index]);
299 #region Protected methods
302 protected internal virtual
306 void OnCollectionChanging (CollectionChangeEventArgs ccevent)
308 if (CollectionChanging != null)
309 CollectionChanging (this, ccevent);
317 void OnCollectionChanged (CollectionChangeEventArgs ccevent)
319 if (CollectionChanged != null)
320 CollectionChanged (this, ccevent);
325 #region Private methods
327 private int IndexOf (string name, string ns, bool error)
329 int index = -1, count = 0, match = -1;
331 index = IndexOf (name, error, index+1);
341 } else if (this [index].Namespace.Equals (ns))
344 } while (index != -1 && index < Count);
349 if (count == 0 || !error)
352 throw new ArgumentException ("The given name '" + name + "' matches atleast two names" +
353 "in the collection object with different namespaces");
357 private int IndexOf (string name, bool error)
360 return IndexOf (name, null, error);
362 return IndexOf (name, error, 0);
366 private int IndexOf (string name, bool error, int start)
368 int count = 0, match = -1;
369 for (int i = start; i < List.Count; i++) {
370 String name2 = ((DataTable) List[i]).TableName;
371 if (String.Compare (name, name2, false) == 0)
373 if (String.Compare (name, name2, true) == 0) {
380 if (count > 1 && error)
381 throw new ArgumentException ("There is no match for the name in the same case and there are multiple matches in different case.");
386 /// gives name to Table (Table1, Table2, Table3,...)
388 private void NameTable (DataTable Table)
390 string Name = "Table";
392 while (Contains (Name + i))
395 Table.TableName = Name + i;
398 // check if a table can be removed from this collectiuon.
399 // if the table can not be remved act according to throwException parameter.
400 // if it is true throws an Exception, else return false.
401 private bool CanRemove (DataTable table, bool throwException)
403 // check if table is null reference
406 throw new ArgumentNullException ("table");
410 // check if the table has the same DataSet as this collection.
411 if (table.DataSet != this.dataSet) {
414 throw new ArgumentException ("Table " + table.TableName + " does not belong to this DataSet.");
417 // check the table has a relation attached to it.
418 if (table.ParentRelations.Count > 0 || table.ChildRelations.Count > 0) {
421 throw new ArgumentException ("Cannot remove a table that has existing relations. Remove relations first.");
424 // now we check if any ForeignKeyConstraint is referncing 'table'.
425 foreach (Constraint c in table.Constraints) {
426 UniqueConstraint uc = c as UniqueConstraint;
428 if (uc.ChildConstraint == null)
433 RaiseForeignKeyReferenceException (table.TableName, uc.ChildConstraint.ConstraintName);
436 ForeignKeyConstraint fc = c as ForeignKeyConstraint;
442 RaiseForeignKeyReferenceException (table.TableName, fc.ConstraintName);
448 private void RaiseForeignKeyReferenceException (string table, string constraint)
450 throw new ArgumentException (String.Format ("Cannot remove table {0}, because it is referenced" +
451 " in ForeignKeyConstraint {1}. Remove the constraint first.",
455 #endregion // Private methods
459 [ResDescriptionAttribute ("Occurs whenever this collection's membership changes.")]
460 public event CollectionChangeEventHandler CollectionChanged;
462 public event CollectionChangeEventHandler CollectionChanging;