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];
87 public DataTable this [string name, string tbNamespace] {
89 int index = IndexOf (name, tbNamespace, true);
90 return index < 0 ? null : (DataTable) List[index];
95 protected override ArrayList List {
96 get { return base.List; }
109 DataTable Table = new DataTable ();
118 void Add (DataTable table)
120 OnCollectionChanging (new CollectionChangeEventArgs (CollectionChangeAction.Add, table));
121 // check if the reference is a null reference
123 throw new ArgumentNullException("table");
125 // check if the list already contains this tabe.
126 if(List.Contains(table))
127 throw new ArgumentException("DataTable already belongs to this DataSet.");
129 // check if table is part of another DataSet
130 if (table.DataSet != null && table.DataSet != this.dataSet)
131 throw new ArgumentException ("DataTable already belongs to another DataSet");
133 // if the table name is null or empty string.
135 if (table.TableName == null || table.TableName == string.Empty)
138 // check if the collection has a table with the same name.
140 int tmp = IndexOf (table.TableName);
142 int tmp = IndexOf (table.TableName, table.Namespace);
144 // if we found a table with same name we have to check
145 // that it is the same case.
146 // indexof can return a table with different case letters.
149 if(table.TableName == this[tmp].TableName)
150 throw new DuplicateNameException("A DataTable named '" + table.TableName + "' already belongs to this DataSet.");
154 table.dataSet = dataSet;
155 OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, table));
162 DataTable Add (string name)
164 DataTable table = new DataTable (name);
170 public DataTable Add (string name, string tbNamespace)
172 DataTable table = new DataTable (name, tbNamespace);
178 public void AddRange (DataTable[] tables)
180 if (dataSet != null && dataSet.InitInProgress) {
181 mostRecentTables = tables;
188 foreach (DataTable table in tables) {
195 internal void PostAddRange ()
197 if (mostRecentTables == null)
200 foreach (DataTable table in mostRecentTables){
205 mostRecentTables = null;
208 public bool CanRemove (DataTable table)
210 return CanRemove(table, false);
218 public bool Contains (string name)
220 return (-1 != IndexOf (name, false));
224 public bool Contains (string name, string tableNamespace)
226 return (IndexOf (name, tableNamespace) != -1) ;
234 int IndexOf (DataTable table)
236 return List.IndexOf (table);
243 int IndexOf (string name)
245 return IndexOf (name, false);
249 public int IndexOf (string name, string tableNamespace)
251 if (tableNamespace == null)
252 throw new ArgumentNullException ("'tableNamespace' argument cannot be null.",
254 return IndexOf (name, tableNamespace, false);
258 public void Remove (DataTable table)
260 OnCollectionChanging (new CollectionChangeEventArgs (CollectionChangeAction.Remove, table));
261 if (CanRemove(table, true))
262 table.dataSet = null;
265 table.dataSet = null;
266 OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, table));
269 public void Remove (string name)
271 int index = IndexOf (name, false);
273 throw new ArgumentException ("Table " + name + " does not belong to this DataSet");
278 public void Remove (string name, string tableNamespace)
280 int index = IndexOf (name, tableNamespace, true);
282 throw new ArgumentException ("Table " + name + " does not belong to this DataSet");
288 public void RemoveAt (int index)
295 #region Protected methods
299 protected internal virtual
303 void OnCollectionChanging (CollectionChangeEventArgs Args)
305 if (CollectionChanging != null)
306 CollectionChanging (this, Args);
315 void OnCollectionChanged (CollectionChangeEventArgs Args)
317 if (CollectionChanged != null)
318 CollectionChanged (this, Args);
323 #region Private methods
325 private int IndexOf (string name, string ns, bool error)
327 int index = -1, count = 0, match = -1;
329 index = IndexOf (name, error, index+1);
339 } else if (this [index].Namespace.Equals (ns))
342 } while (index != -1 && index < Count);
347 if (count == 0 || !error)
350 throw new ArgumentException ("The given name '" + name + "' matches atleast two names" +
351 "in the collection object with different namespaces");
355 private int IndexOf (string name, bool error)
358 return IndexOf (name, null, error);
360 return IndexOf (name, error, 0);
364 private int IndexOf (string name, bool error, int start)
366 int count = 0, match = -1;
367 for (int i = start; i < List.Count; i++)
369 String name2 = ((DataTable) List[i]).TableName;
370 if (String.Compare (name, name2, false) == 0)
372 if (String.Compare (name, name2, true) == 0) {
379 if (count > 1 && error)
380 throw new ArgumentException ("There is no match for the name in the same case and there are multiple matches in different case.");
385 /// gives name to Table (Table1, Table2, Table3,...)
387 private void NameTable (DataTable Table)
389 string Name = "Table";
391 while (Contains (Name + i))
394 Table.TableName = Name + i;
397 // check if a table can be removed from this collectiuon.
398 // if the table can not be remved act according to throwException parameter.
399 // if it is true throws an Exception, else return false.
400 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;