2 // System.Data.DataRelationCollection.cs
5 // Christopher Podurgiel (cpodurgiel@msn.com)
6 // Daniel Morgan <danmorg@sc.rr.com>
7 // Tim Coleman (tim@timcoleman.com)
8 // Alan Tam Siu Lung <Tam@SiuLung.com>
10 // (C) Chris Podurgiel
11 // (C) 2002 Daniel Morgan
12 // Copyright (C) Tim Coleman, 2002
16 using System.Collections;
17 using System.ComponentModel;
19 namespace System.Data {
21 /// Represents the collection of DataRelation objects for this DataSet.
24 [DefaultEvent ("CollectionChanged")]
26 public abstract class DataRelationCollection : InternalDataCollectionBase
29 /// Summary description for DataTableRelationCollection.
31 internal class DataSetRelationCollection : DataRelationCollection
33 private DataSet dataSet;
36 /// Initializes a new instance of the DataSetRelationCollection class.
38 internal DataSetRelationCollection (DataSet dataSet)
40 this.dataSet = dataSet;
44 /// Gets the DataRelation object specified by name.
46 public override DataRelation this [string name]
49 foreach (DataRelation dataRelation in List)
50 if (dataRelation.RelationName == name) return dataRelation;
56 /// Gets the DataRelation object at the specified index.
58 public override DataRelation this [int index]
61 return List [index] as DataRelation;
65 protected override DataSet GetDataSet()
71 /// Performs verification on the table.
73 /// <param name="relation">The relation to check.</param>
74 protected override void AddCore (DataRelation relation)
76 base.AddCore (relation);
77 if (relation.ChildTable.DataSet != this.dataSet || relation.ParentTable.DataSet != this.dataSet)
78 throw new DataException ();
79 //List.Add (relation);
80 relation.SetDataSet (dataSet);
81 relation.ParentTable.ChildRelations.Add (relation);
82 relation.ChildTable.ParentRelations.Add (relation);
83 ForeignKeyConstraint foreignKeyConstraint = null;
84 if (relation.createConstraints)
86 foreignKeyConstraint = new ForeignKeyConstraint (relation.RelationName, relation.ParentColumns, relation.ChildColumns);
87 relation.ChildTable.Constraints.Add (foreignKeyConstraint);
89 UniqueConstraint uniqueConstraint = null;
90 ConstraintCollection parentConstrains = relation.ParentTable.Constraints;
91 // find if the unique constraint already exists in the parent table.
92 foreach (Constraint o in parentConstrains)
94 if (o is UniqueConstraint)
96 UniqueConstraint uc = (UniqueConstraint) o;
97 if (uc.Columns.Length == relation.ParentColumns.Length)
99 bool allColumnsEqual = true;
100 for (int columnCnt = 0; columnCnt < uc.Columns.Length; ++columnCnt)
102 if (uc.Columns[columnCnt] != relation.ParentColumns[columnCnt])
104 allColumnsEqual = false;
110 uniqueConstraint = uc;
116 // if we did not find the unique constraint in the parent table.
117 // we generate new uniqueconastraint and add it to the parent table.
118 if (uniqueConstraint == null)
120 uniqueConstraint = new UniqueConstraint(relation.ParentColumns, false);
121 relation.ParentTable.Constraints.Add(uniqueConstraint);
123 relation.SetParentKeyConstraint (uniqueConstraint);
124 relation.SetChildKeyConstraint (foreignKeyConstraint);
128 public override void AddRange (DataRelation[] relations)
130 base.AddRange (relations);
133 public override void Clear ()
135 for (int i = 0; i < Count; i++)
141 protected override void RemoveCore (DataRelation relation)
143 relation.SetDataSet (null);
144 relation.ParentTable.ChildRelations.Remove (relation);
145 relation.ChildTable.ParentRelations.Remove (relation);
146 relation.SetParentKeyConstraint (null);
147 relation.SetChildKeyConstraint (null);
150 protected override ArrayList List {
158 /// Summary description for DataTableRelationCollection.
160 internal class DataTableRelationCollection : DataRelationCollection
162 private DataTable dataTable;
165 /// Initializes a new instance of the DataTableRelationCollection class.
167 internal DataTableRelationCollection (DataTable dataTable)
169 this.dataTable = dataTable;
173 /// Gets the DataRelation object specified by name.
175 public override DataRelation this [string name]
178 foreach (DataRelation dataRelation in List)
179 if (dataRelation.RelationName == name) return dataRelation;
185 /// Gets the DataRelation object at the specified index.
187 public override DataRelation this [int index]
190 return List [index] as DataRelation;
194 protected override DataSet GetDataSet()
196 return dataTable.DataSet;
199 protected override void AddCore (DataRelation relation)
201 base.AddCore (relation);
204 protected override void RemoveCore (DataRelation relation)
206 base.RemoveCore (relation);
209 protected override ArrayList List {
216 private int defaultNameIndex;
217 private bool inTransition;
222 /// Initializes a new instance of the DataRelationCollection class.
224 protected DataRelationCollection ()
227 defaultNameIndex = 1;
228 inTransition = false;
232 /// Gets the DataRelation object specified by name.
234 public abstract DataRelation this[string name]{get;}
237 /// Gets the DataRelation object at the specified index.
239 public abstract DataRelation this[int index]{get;}
243 private string GetNextDefaultRelationName ()
245 string defRelationName = "Relation";
246 for (int index = 1; Contains (defRelationName); ++index) {
247 defRelationName = "Relation" + index;
249 return defRelationName;
253 /// Adds a DataRelation to the DataRelationCollection.
255 /// <param name="relation">The DataRelation to add to the collection.</param>
257 public void Add(DataRelation relation)
259 this.AddCore (relation);
260 if(relation.RelationName == string.Empty)
261 relation.RelationName = GenerateRelationName();
262 CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
264 OnCollectionChanged(e);
267 private string GenerateRelationName()
270 return "Relation" + index;
274 /// Creates a relation given the parameters and adds it to the collection. The name is defaulted.
275 /// An ArgumentException is generated if this relation already belongs to this collection or belongs to another collection.
276 /// An InvalidConstraintException is generated if the relation can't be created based on the parameters.
277 /// The CollectionChanged event is fired if it succeeds.
279 /// <param name="parentColumn">parent column of relation.</param>
280 /// <param name="childColumn">child column of relation.</param>
281 /// <returns>The created DataRelation.</returns>
282 public virtual DataRelation Add(DataColumn parentColumn, DataColumn childColumn)
284 DataRelation dataRelation = new DataRelation(GetNextDefaultRelationName (), parentColumn, childColumn);
290 /// Creates a relation given the parameters and adds it to the collection. The name is defaulted.
291 /// An ArgumentException is generated if this relation already belongs to this collection or belongs to another collection.
292 /// An InvalidConstraintException is generated if the relation can't be created based on the parameters.
293 /// The CollectionChanged event is raised if it succeeds.
295 /// <param name="parentColumns">An array of parent DataColumn objects.</param>
296 /// <param name="childColumns">An array of child DataColumn objects.</param>
297 /// <returns>The created DataRelation.</returns>
298 public virtual DataRelation Add(DataColumn[] parentColumns, DataColumn[] childColumns)
300 DataRelation dataRelation = new DataRelation(GetNextDefaultRelationName (), parentColumns, childColumns);
306 /// Creates a relation given the parameters and adds it to the collection.
307 /// An ArgumentException is generated if this relation already belongs to this collection or belongs to another collection.
308 /// A DuplicateNameException is generated if this collection already has a relation with the same name (case insensitive).
309 /// An InvalidConstraintException is generated if the relation can't be created based on the parameters.
310 /// The CollectionChanged event is raised if it succeeds.
312 /// <param name="name">The name of the relation.</param>
313 /// <param name="parentColumn">parent column of relation.</param>
314 /// <returns>The created DataRelation.</returns>
315 /// <returns></returns>
316 public virtual DataRelation Add(string name, DataColumn parentColumn, DataColumn childColumn)
318 //If no name was supplied, give it a default name.
319 if (name == null || name == "") name = GetNextDefaultRelationName ();
321 DataRelation dataRelation = new DataRelation(name, parentColumn, childColumn);
327 /// Creates a DataRelation with the specified name, and arrays of parent and child columns, and adds it to the collection.
329 /// <param name="name">The name of the DataRelation to create.</param>
330 /// <param name="parentColumns">An array of parent DataColumn objects.</param>
331 /// <param name="childColumns">An array of child DataColumn objects.</param>
332 /// <returns>The created DataRelation.</returns>
333 public virtual DataRelation Add(string name, DataColumn[] parentColumns, DataColumn[] childColumns)
335 //If no name was supplied, give it a default name.
336 if (name == null || name == "") name = GetNextDefaultRelationName ();
338 DataRelation dataRelation = new DataRelation(name, parentColumns, childColumns);
344 /// Creates a relation given the parameters and adds it to the collection.
345 /// An ArgumentException is generated if this relation already belongs to this collection or belongs to another collection.
346 /// A DuplicateNameException is generated if this collection already has a relation with the same name (case insensitive).
347 /// An InvalidConstraintException is generated if the relation can't be created based on the parameters.
348 /// The CollectionChanged event is raised if it succeeds.
350 /// <param name="name">The name of the relation.</param>
351 /// <param name="parentColumn">parent column of relation.</param>
352 /// <param name="childColumn">child column of relation.</param>
353 /// <param name="createConstraints">true to create constraints; otherwise false. (default is true)</param>
354 /// <returns>The created DataRelation.</returns>
355 public virtual DataRelation Add(string name, DataColumn parentColumn, DataColumn childColumn, bool createConstraints)
357 //If no name was supplied, give it a default name.
358 if (name == null || name == "") name = GetNextDefaultRelationName ();
360 DataRelation dataRelation = new DataRelation(name, parentColumn, childColumn, createConstraints);
366 /// Creates a DataRelation with the specified name, arrays of parent and child columns,
367 /// and value specifying whether to create a constraint, and adds it to the collection.
369 /// <param name="name">The name of the DataRelation to create.</param>
370 /// <param name="parentColumns">An array of parent DataColumn objects.</param>
371 /// <param name="childColumns">An array of child DataColumn objects.</param>
372 /// <param name="createConstraints">true to create a constraint; otherwise false.</param>
373 /// <returns>The created DataRelation.</returns>
374 public virtual DataRelation Add(string name, DataColumn[] parentColumns, DataColumn[] childColumns, bool createConstraints)
376 //If no name was supplied, give it a default name.
377 if (name == null || name == "") name = GetNextDefaultRelationName ();
379 DataRelation dataRelation = new DataRelation(name, parentColumns, childColumns, createConstraints);
386 /// Performs verification on the table.
388 /// <param name="relation">The relation to check.</param>
390 protected virtual void AddCore(DataRelation relation)
392 if (relation == null)
394 //TODO: Issue a good exception message.
395 throw new ArgumentNullException();
397 else if(List.IndexOf(relation) != -1)
399 //TODO: Issue a good exception message.
400 throw new ArgumentException();
402 else if(List.Contains(relation.RelationName))
404 //TODO: Issue a good exception message.
405 throw new DuplicateNameException("A Relation named " + relation.RelationName + " already belongs to this DataSet.");
410 /// Copies the elements of the specified DataRelation array to the end of the collection.
412 /// <param name="relations">The array of DataRelation objects to add to the collection.</param>
413 public virtual void AddRange(DataRelation[] relations)
415 foreach (DataRelation relation in relations) Add(relation);
419 public virtual bool CanRemove(DataRelation relation)
425 public virtual void Clear()
430 public virtual bool Contains(string name)
432 return IndexOf(name) != -1;
435 private CollectionChangeEventArgs CreateCollectionChangeEvent (CollectionChangeAction action)
437 return new CollectionChangeEventArgs (action, this);
440 protected abstract DataSet GetDataSet();
442 public virtual int IndexOf(DataRelation relation)
444 return List.IndexOf(relation);
447 public virtual int IndexOf(string relationName)
449 return List.IndexOf(this[relationName]);
452 protected virtual void OnCollectionChanged (CollectionChangeEventArgs ccevent)
454 if (CollectionChanged != null)
455 CollectionChanged (this, ccevent);
459 protected internal virtual void OnCollectionChanging (CollectionChangeEventArgs ccevent)
461 throw new NotImplementedException ();
464 public void Remove (DataRelation relation)
466 RemoveCore (relation);
467 List.Remove (relation);
468 string name = "Relation" + index;
469 if (relation.RelationName == name)
471 OnCollectionChanged (CreateCollectionChangeEvent (CollectionChangeAction.Remove));
474 public void Remove (string name)
476 Remove ((DataRelation) List[IndexOf (name)]);
479 public void RemoveAt (int index)
485 protected virtual void RemoveCore(DataRelation relation)
487 // TODO: What have to be done?
490 [ResDescriptionAttribute ("Occurs whenever this collection's membership changes.")]
491 public event CollectionChangeEventHandler CollectionChanged;