2 // System.Data.DataTableCollection.cs
5 // Christopher Podurgiel (cpodurgiel@msn.com)
6 // Tim Coleman <tim@timcoleman.com>
9 // (C) Copyright 2002 Tim Coleman
13 using System.Collections;
14 using System.ComponentModel;
15 using System.Globalization;
17 namespace System.Data {
19 /// Represents the collection of tables for the DataSet.
22 [DefaultEvent ("CollectionChanged")]
23 [ListBindable (false)]
25 public class DataTableCollection : InternalDataCollectionBase
31 internal DataTableCollection (DataSet dataSet)
34 this.dataSet = dataSet;
41 public DataTable this[int index] {
42 get { return (DataTable)(list[index]); }
45 public DataTable this[string name] {
47 int index = IndexOf (name, true);
48 return index < 0 ? null : (DataTable) list[index];
54 public DataTable this [string name, string tbNamespace] {
55 get { throw new NotImplementedException (); }
59 protected override ArrayList List {
67 public virtual DataTable Add ()
69 DataTable Table = new DataTable ();
74 public virtual void Add (DataTable table)
77 // check if the reference is a null reference
79 throw new ArgumentNullException("table");
81 // check if the list already contains this tabe.
82 if(list.Contains(table))
83 throw new ArgumentException("DataTable already belongs to this DataSet.");
85 // if the table name is null or empty string.
87 if (table.TableName == null || table.TableName == string.Empty)
90 // check if the collection has a table with the same name.
91 int tmp = IndexOf(table.TableName);
92 // if we found a table with same name we have to check
93 // that it is the same case.
94 // indexof can return a table with different case letters.
97 if(table.TableName == this[tmp].TableName)
98 throw new DuplicateNameException("A DataTable named '" + table.TableName + "' already belongs to this DataSet.");
102 table.dataSet = dataSet;
103 OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, table));
106 public virtual DataTable Add (string name)
108 DataTable table = new DataTable (name);
114 public virtual DataTable Add (string name, string tbNamespace)
116 DataTable table = new DataTable (name, tbNamespace);
122 public void AddRange (DataTable[] tables)
124 foreach (DataTable table in tables)
129 public bool CanRemove (DataTable table)
131 return CanRemove(table, false);
139 public bool Contains (string name)
141 return (-1 != IndexOf (name, false));
144 public virtual int IndexOf (DataTable table)
146 return list.IndexOf (table);
149 public virtual int IndexOf (string name)
151 return IndexOf (name, false);
154 public void Remove (DataTable table)
156 CanRemove(table, true);
158 OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, table));
161 public void Remove (string name)
163 Remove (this [name]);
166 public void RemoveAt (int index)
168 DataTable t = this[index];
170 list.RemoveAt (index);
171 OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, t));
176 #region Protected methods
178 protected internal virtual void OnCollectionChanging (CollectionChangeEventArgs Args)
180 if (CollectionChanging != null)
181 CollectionChanging (this, Args);
184 protected virtual void OnCollectionChanged (CollectionChangeEventArgs Args)
186 if (CollectionChanged != null)
187 CollectionChanged (this, Args);
192 #region Private methods
194 private int IndexOf (string name, bool error)
196 int count = 0, match = -1;
197 for (int i = 0; i < list.Count; i++)
199 String name2 = ((DataTable) list[i]).TableName;
200 if (String.Compare (name, name2, true) == 0)
202 if (String.Compare (name, name2, false) == 0)
210 if (count > 1 && error)
211 throw new ArgumentException ("There is no match for the name in the same case and there are multiple matches in different case.");
216 /// gives name to Table (Table1, Table2, Table3,...)
218 private void NameTable (DataTable Table)
220 string Name = "Table";
222 while (Contains (Name + i))
225 Table.TableName = Name + i;
228 // check if a table can be removed from this collectiuon.
229 // if the table can not be remved act according to throwException parameter.
230 // if it is true throws an Exception, else return false.
231 private bool CanRemove(DataTable table, bool throwException)
233 // check if table is null reference
237 throw new ArgumentNullException("table");
241 // check if the table has the same DataSet as this collection.
242 if(table.DataSet != this.dataSet)
245 throw new ArgumentException("Table " + table.TableName + " does not belong to this DataSet.");
249 // check the table has a relation attached to it.
250 if (table.ParentRelations.Count > 0 || table.ChildRelations.Count > 0)
253 throw new ArgumentException("Cannot remove a table that has existing relations. Remove relations first.");
258 // now we check if any ForeignKeyConstraint is referncing 'table'.
259 IEnumerator tableEnumerator = this.dataSet.Tables.GetEnumerator();
261 // loop on all tables in dataset
262 while (tableEnumerator.MoveNext())
264 IEnumerator constraintEnumerator = ((DataTable) tableEnumerator.Current).Constraints.GetEnumerator();
265 // loop on all constrains in the current table
266 while (constraintEnumerator.MoveNext())
268 Object o = constraintEnumerator.Current;
269 // we only check ForeignKeyConstraint
270 if (o is ForeignKeyConstraint)
272 ForeignKeyConstraint fc = (ForeignKeyConstraint) o;
273 if(fc.Table == table || fc.RelatedTable == table)
276 throw new ArgumentException("Cannot remove table " + table.TableName + ", because it referenced in ForeignKeyConstraint " + fc.ConstraintName + ". Remove the constraint first.");
286 #endregion // Private methods
290 [ResDescriptionAttribute ("Occurs whenever this collection's membership changes.")]
291 public event CollectionChangeEventHandler CollectionChanged;
293 public event CollectionChangeEventHandler CollectionChanging;