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;
40 namespace System.Data {
42 /// Represents the collection of tables for the DataSet.
44 [Editor ("Microsoft.VSDesigner.Data.Design.TablesCollectionEditor, " + Consts.AssemblyMicrosoft_VSDesigner,
45 "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
46 [DefaultEvent ("CollectionChanged")]
47 [ListBindable (false)]
55 class DataTableCollection : InternalDataCollectionBase
58 DataTable[] mostRecentTables;
61 internal DataTableCollection (DataSet dataSet)
64 this.dataSet = dataSet;
71 public DataTable this[int index] {
73 if (index < 0 || index >= List.Count)
74 throw new IndexOutOfRangeException(String.Format("Cannot find table {0}", index));
75 return (DataTable)(List[index]);
79 public DataTable this[string name] {
81 int index = IndexOf (name, true);
82 return index < 0 ? null : (DataTable) List[index];
88 public DataTable this [string name, string tbNamespace] {
89 get { throw new NotImplementedException (); }
93 protected override ArrayList List {
94 get { return base.List; }
107 DataTable Table = new DataTable ();
116 void Add (DataTable table)
118 OnCollectionChanging (new CollectionChangeEventArgs (CollectionChangeAction.Add, table));
119 // check if the reference is a null reference
121 throw new ArgumentNullException("table");
123 // check if the list already contains this tabe.
124 if(List.Contains(table))
125 throw new ArgumentException("DataTable already belongs to this DataSet.");
127 // check if table is part of another DataSet
128 if (table.DataSet != null && table.DataSet != this.dataSet)
129 throw new ArgumentException ("DataTable already belongs to another DataSet");
131 // if the table name is null or empty string.
133 if (table.TableName == null || table.TableName == string.Empty)
136 // check if the collection has a table with the same name.
137 int tmp = IndexOf(table.TableName);
138 // if we found a table with same name we have to check
139 // that it is the same case.
140 // indexof can return a table with different case letters.
143 if(table.TableName == this[tmp].TableName)
144 throw new DuplicateNameException("A DataTable named '" + table.TableName + "' already belongs to this DataSet.");
148 table.dataSet = dataSet;
149 OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, table));
156 DataTable Add (string name)
158 DataTable table = new DataTable (name);
164 public DataTable Add (string name, string tbNamespace)
166 DataTable table = new DataTable (name, tbNamespace);
172 public void AddRange (DataTable[] tables)
174 if (dataSet != null && dataSet.InitInProgress) {
175 mostRecentTables = tables;
182 foreach (DataTable table in tables) {
189 internal void PostAddRange ()
191 if (mostRecentTables == null)
194 foreach (DataTable table in mostRecentTables){
199 mostRecentTables = null;
202 public bool CanRemove (DataTable table)
204 return CanRemove(table, false);
212 public bool Contains (string name)
214 return (-1 != IndexOf (name, false));
221 int IndexOf (DataTable table)
223 return List.IndexOf (table);
230 int IndexOf (string name)
232 return IndexOf (name, false);
235 public void Remove (DataTable table)
237 OnCollectionChanging (new CollectionChangeEventArgs (CollectionChangeAction.Remove, table));
238 if (CanRemove(table, true))
239 table.dataSet = null;
242 table.dataSet = null;
243 OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, table));
246 public void Remove (string name)
248 if ( IndexOf (name, false) == -1)
249 throw new ArgumentException ("Table " + name + " does not belong to this DataSet");
250 Remove (this [name]);
253 public void RemoveAt (int index)
260 #region Protected methods
266 void OnCollectionChanging (CollectionChangeEventArgs Args)
268 if (CollectionChanging != null)
269 CollectionChanging (this, Args);
276 void OnCollectionChanged (CollectionChangeEventArgs Args)
278 if (CollectionChanged != null)
279 CollectionChanged (this, Args);
284 #region Private methods
286 private int IndexOf (string name, bool error)
288 int count = 0, match = -1;
289 for (int i = 0; i < List.Count; i++)
291 String name2 = ((DataTable) List[i]).TableName;
292 if (String.Compare (name, name2, true) == 0)
294 if (String.Compare (name, name2, false) == 0)
302 if (count > 1 && error)
303 throw new ArgumentException ("There is no match for the name in the same case and there are multiple matches in different case.");
308 /// gives name to Table (Table1, Table2, Table3,...)
310 private void NameTable (DataTable Table)
312 string Name = "Table";
314 while (Contains (Name + i))
317 Table.TableName = Name + i;
320 // check if a table can be removed from this collectiuon.
321 // if the table can not be remved act according to throwException parameter.
322 // if it is true throws an Exception, else return false.
323 private bool CanRemove(DataTable table, bool throwException)
326 // check if table is null reference
330 throw new ArgumentNullException("table");
334 // check if the table doesnot belong to this collection
335 bool tableexists = true;
336 int tmp = IndexOf(table.TableName);
337 // if we found a table with same name we have to check
338 // that it is the same case.
339 // indexof can return a table with different case letters.
342 if(table.TableName != this[tmp].TableName)
351 throw new ArgumentException("Table does not exist in collection");
357 // check if the table has the same DataSet as this collection.
358 if(table.DataSet != this.dataSet)
361 throw new ArgumentException("Table " + table.TableName + " does not belong to this DataSet.");
365 // check the table has a relation attached to it.
366 if (table.ParentRelations.Count > 0 || table.ChildRelations.Count > 0)
369 throw new ArgumentException("Cannot remove a table that has existing relations. Remove relations first.");
374 // now we check if any ForeignKeyConstraint is referncing 'table'.
375 IEnumerator tableEnumerator = this.dataSet.Tables.GetEnumerator();
377 // loop on all tables in dataset
378 while (tableEnumerator.MoveNext())
380 IEnumerator constraintEnumerator = ((DataTable) tableEnumerator.Current).Constraints.GetEnumerator();
381 // loop on all constrains in the current table
382 while (constraintEnumerator.MoveNext())
384 Object o = constraintEnumerator.Current;
385 // we only check ForeignKeyConstraint
386 if (o is ForeignKeyConstraint)
388 ForeignKeyConstraint fc = (ForeignKeyConstraint) o;
389 if(fc.Table == table || fc.RelatedTable == table)
392 throw new ArgumentException("Cannot remove table " + table.TableName + ", because it referenced in ForeignKeyConstraint " + fc.ConstraintName + ". Remove the constraint first.");
402 #endregion // Private methods
406 [ResDescriptionAttribute ("Occurs whenever this collection's membership changes.")]
407 public event CollectionChangeEventHandler CollectionChanged;
409 public event CollectionChangeEventHandler CollectionChanging;