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) ;
230 public void CopyTo (DataTable [] array, int index)
232 CopyTo ((Array) array, index);
239 int IndexOf (DataTable table)
241 return List.IndexOf (table);
248 int IndexOf (string name)
250 return IndexOf (name, false);
254 public int IndexOf (string name, string tableNamespace)
256 if (tableNamespace == null)
257 throw new ArgumentNullException ("'tableNamespace' argument cannot be null.",
259 return IndexOf (name, tableNamespace, false);
263 public void Remove (DataTable table)
265 OnCollectionChanging (new CollectionChangeEventArgs (CollectionChangeAction.Remove, table));
266 if (CanRemove(table, true))
267 table.dataSet = null;
270 table.dataSet = null;
271 OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, table));
274 public void Remove (string name)
276 int index = IndexOf (name, false);
278 throw new ArgumentException ("Table " + name + " does not belong to this DataSet");
283 public void Remove (string name, string tableNamespace)
285 int index = IndexOf (name, tableNamespace, true);
287 throw new ArgumentException ("Table " + name + " does not belong to this DataSet");
293 public void RemoveAt (int index)
300 #region Protected methods
304 protected internal virtual
308 void OnCollectionChanging (CollectionChangeEventArgs Args)
310 if (CollectionChanging != null)
311 CollectionChanging (this, Args);
320 void OnCollectionChanged (CollectionChangeEventArgs Args)
322 if (CollectionChanged != null)
323 CollectionChanged (this, Args);
328 #region Private methods
330 private int IndexOf (string name, string ns, bool error)
332 int index = -1, count = 0, match = -1;
334 index = IndexOf (name, error, index+1);
344 } else if (this [index].Namespace.Equals (ns))
347 } while (index != -1 && index < Count);
352 if (count == 0 || !error)
355 throw new ArgumentException ("The given name '" + name + "' matches atleast two names" +
356 "in the collection object with different namespaces");
360 private int IndexOf (string name, bool error)
363 return IndexOf (name, null, error);
365 return IndexOf (name, error, 0);
369 private int IndexOf (string name, bool error, int start)
371 int count = 0, match = -1;
372 for (int i = start; i < List.Count; i++)
374 String name2 = ((DataTable) List[i]).TableName;
375 if (String.Compare (name, name2, false) == 0)
377 if (String.Compare (name, name2, true) == 0) {
384 if (count > 1 && error)
385 throw new ArgumentException ("There is no match for the name in the same case and there are multiple matches in different case.");
390 /// gives name to Table (Table1, Table2, Table3,...)
392 private void NameTable (DataTable Table)
394 string Name = "Table";
396 while (Contains (Name + i))
399 Table.TableName = Name + i;
402 // check if a table can be removed from this collectiuon.
403 // if the table can not be remved act according to throwException parameter.
404 // if it is true throws an Exception, else return false.
405 private bool CanRemove(DataTable table, bool throwException)
408 // check if table is null reference
411 throw new ArgumentNullException("table");
415 // check if the table has the same DataSet as this collection.
416 if(table.DataSet != this.dataSet) {
419 throw new ArgumentException("Table " + table.TableName + " does not belong to this DataSet.");
422 // check the table has a relation attached to it.
423 if (table.ParentRelations.Count > 0 || table.ChildRelations.Count > 0) {
426 throw new ArgumentException("Cannot remove a table that has existing relations. Remove relations first.");
429 // now we check if any ForeignKeyConstraint is referncing 'table'.
430 foreach (Constraint c in table.Constraints) {
431 UniqueConstraint uc = c as UniqueConstraint;
433 if (uc.ChildConstraint == null)
438 RaiseForeignKeyReferenceException (table.TableName, uc.ChildConstraint.ConstraintName);
441 ForeignKeyConstraint fc = c as ForeignKeyConstraint;
447 RaiseForeignKeyReferenceException (table.TableName, fc.ConstraintName);
453 private void RaiseForeignKeyReferenceException (string table, string constraint)
455 throw new ArgumentException (String.Format ("Cannot remove table {0}, because it is referenced" +
456 " in ForeignKeyConstraint {1}. Remove the constraint first.",
460 #endregion // Private methods
464 [ResDescriptionAttribute ("Occurs whenever this collection's membership changes.")]
465 public event CollectionChangeEventHandler CollectionChanged;
467 public event CollectionChangeEventHandler CollectionChanging;