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 ();
80 relation.SetDataSet (dataSet);
81 relation.ParentTable.ChildRelations.Add (relation);
82 relation.ChildTable.ParentRelations.Add (relation);
83 ForeignKeyConstraint foreignKeyConstraint = null;
84 if (relation.createConstraints) {
85 foreignKeyConstraint = new ForeignKeyConstraint (relation.ParentColumns, relation.ChildColumns);
86 relation.ChildTable.Constraints.Add (foreignKeyConstraint);
88 UniqueConstraint uniqueConstraint = null;
89 foreach (object o in List) {
90 if (o is UniqueConstraint) {
91 UniqueConstraint uc = (UniqueConstraint) o;
92 if (uc.Columns.Length == relation.ParentColumns.Length) {
93 bool allColumnsEqual = true;
94 for (int columnCnt = 0; columnCnt < uc.Columns.Length; ++columnCnt) {
95 if (uc.Columns[columnCnt] != relation.ParentColumns[columnCnt]) {
96 allColumnsEqual = false;
100 if (allColumnsEqual) {
101 uniqueConstraint = uc;
107 // if we did not find the unique constraint in the parent table.
108 // we generate new uniqueconastraint and add it to the parent table.
109 if (uniqueConstraint == null)
111 uniqueConstraint = new UniqueConstraint(relation.ParentColumns, false);
112 relation.ParentTable.Constraints.Add(uniqueConstraint);
114 relation.SetParentKeyConstraint (uniqueConstraint);
115 relation.SetChildKeyConstraint (foreignKeyConstraint);
118 public override void AddRange (DataRelation[] relations)
120 base.AddRange (relations);
123 public override void Clear ()
128 protected override void RemoveCore (DataRelation relation)
130 base.RemoveCore (relation);
131 relation.SetDataSet (null);
132 relation.ParentTable.ChildRelations.Remove (relation);
133 relation.ChildTable.ParentRelations.Remove (relation);
134 ForeignKeyConstraint foreignKeyConstraint = null;
135 relation.SetParentKeyConstraint (null);
136 relation.SetChildKeyConstraint (null);
139 protected override ArrayList List {
147 /// Summary description for DataTableRelationCollection.
149 internal class DataTableRelationCollection : DataRelationCollection
151 private DataTable dataTable;
154 /// Initializes a new instance of the DataTableRelationCollection class.
156 internal DataTableRelationCollection (DataTable dataTable)
158 this.dataTable = dataTable;
162 /// Gets the DataRelation object specified by name.
164 public override DataRelation this [string name]
167 foreach (DataRelation dataRelation in List)
168 if (dataRelation.RelationName == name) return dataRelation;
174 /// Gets the DataRelation object at the specified index.
176 public override DataRelation this [int index]
179 return List [index] as DataRelation;
183 protected override DataSet GetDataSet()
185 return dataTable.DataSet;
188 protected override void AddCore (DataRelation relation)
190 base.AddCore (relation);
193 protected override void RemoveCore (DataRelation relation)
195 base.RemoveCore (relation);
198 protected override ArrayList List {
205 private int defaultNameIndex;
206 private bool inTransition;
211 /// Initializes a new instance of the DataRelationCollection class.
213 protected DataRelationCollection ()
216 defaultNameIndex = 1;
217 inTransition = false;
221 /// Gets the DataRelation object specified by name.
223 public abstract DataRelation this[string name]{get;}
226 /// Gets the DataRelation object at the specified index.
228 public abstract DataRelation this[int index]{get;}
232 private string GetNextDefaultRelationName ()
234 string defRelationName = "Relation";
235 for (int index = 1; Contains (defRelationName); ++index) {
236 defRelationName = "Relation" + index;
238 return defRelationName;
242 /// Adds a DataRelation to the DataRelationCollection.
244 /// <param name="relation">The DataRelation to add to the collection.</param>
246 public void Add(DataRelation relation)
248 this.AddCore (relation);
249 if(relation.RelationName == string.Empty)
250 relation.RelationName = GenerateRelationName();
251 CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
253 OnCollectionChanged(e);
256 private string GenerateRelationName()
259 return "Relation" + index;
263 /// Creates a relation given the parameters and adds it to the collection. The name is defaulted.
264 /// An ArgumentException is generated if this relation already belongs to this collection or belongs to another collection.
265 /// An InvalidConstraintException is generated if the relation can't be created based on the parameters.
266 /// The CollectionChanged event is fired if it succeeds.
268 /// <param name="parentColumn">parent column of relation.</param>
269 /// <param name="childColumn">child column of relation.</param>
270 /// <returns>The created DataRelation.</returns>
271 public virtual DataRelation Add(DataColumn parentColumn, DataColumn childColumn)
273 DataRelation dataRelation = new DataRelation(GetNextDefaultRelationName (), parentColumn, childColumn);
279 /// Creates a relation given the parameters and adds it to the collection. The name is defaulted.
280 /// An ArgumentException is generated if this relation already belongs to this collection or belongs to another collection.
281 /// An InvalidConstraintException is generated if the relation can't be created based on the parameters.
282 /// The CollectionChanged event is raised if it succeeds.
284 /// <param name="parentColumns">An array of parent DataColumn objects.</param>
285 /// <param name="childColumns">An array of child DataColumn objects.</param>
286 /// <returns>The created DataRelation.</returns>
287 public virtual DataRelation Add(DataColumn[] parentColumns, DataColumn[] childColumns)
289 DataRelation dataRelation = new DataRelation(GetNextDefaultRelationName (), parentColumns, childColumns);
295 /// Creates a relation given the parameters and adds it to the collection.
296 /// An ArgumentException is generated if this relation already belongs to this collection or belongs to another collection.
297 /// A DuplicateNameException is generated if this collection already has a relation with the same name (case insensitive).
298 /// An InvalidConstraintException is generated if the relation can't be created based on the parameters.
299 /// The CollectionChanged event is raised if it succeeds.
301 /// <param name="name">The name of the relation.</param>
302 /// <param name="parentColumn">parent column of relation.</param>
303 /// <returns>The created DataRelation.</returns>
304 /// <returns></returns>
305 public virtual DataRelation Add(string name, DataColumn parentColumn, DataColumn childColumn)
307 //If no name was supplied, give it a default name.
308 if (name == null || name == "") name = GetNextDefaultRelationName ();
310 DataRelation dataRelation = new DataRelation(name, parentColumn, childColumn);
316 /// Creates a DataRelation with the specified name, and arrays of parent and child columns, and adds it to the collection.
318 /// <param name="name">The name of the DataRelation to create.</param>
319 /// <param name="parentColumns">An array of parent DataColumn objects.</param>
320 /// <param name="childColumns">An array of child DataColumn objects.</param>
321 /// <returns>The created DataRelation.</returns>
322 public virtual DataRelation Add(string name, DataColumn[] parentColumns, DataColumn[] childColumns)
324 //If no name was supplied, give it a default name.
325 if (name == null || name == "") name = GetNextDefaultRelationName ();
327 DataRelation dataRelation = new DataRelation(name, parentColumns, childColumns);
333 /// Creates a relation given the parameters and adds it to the collection.
334 /// An ArgumentException is generated if this relation already belongs to this collection or belongs to another collection.
335 /// A DuplicateNameException is generated if this collection already has a relation with the same name (case insensitive).
336 /// An InvalidConstraintException is generated if the relation can't be created based on the parameters.
337 /// The CollectionChanged event is raised if it succeeds.
339 /// <param name="name">The name of the relation.</param>
340 /// <param name="parentColumn">parent column of relation.</param>
341 /// <param name="childColumn">child column of relation.</param>
342 /// <param name="createConstraints">true to create constraints; otherwise false. (default is true)</param>
343 /// <returns>The created DataRelation.</returns>
344 public virtual DataRelation Add(string name, DataColumn parentColumn, DataColumn childColumn, bool createConstraints)
346 //If no name was supplied, give it a default name.
347 if (name == null || name == "") name = GetNextDefaultRelationName ();
349 DataRelation dataRelation = new DataRelation(name, parentColumn, childColumn, createConstraints);
355 /// Creates a DataRelation with the specified name, arrays of parent and child columns,
356 /// and value specifying whether to create a constraint, and adds it to the collection.
358 /// <param name="name">The name of the DataRelation to create.</param>
359 /// <param name="parentColumns">An array of parent DataColumn objects.</param>
360 /// <param name="childColumns">An array of child DataColumn objects.</param>
361 /// <param name="createConstraints">true to create a constraint; otherwise false.</param>
362 /// <returns>The created DataRelation.</returns>
363 public virtual DataRelation Add(string name, DataColumn[] parentColumns, DataColumn[] childColumns, bool createConstraints)
365 //If no name was supplied, give it a default name.
366 if (name == null || name == "") name = GetNextDefaultRelationName ();
368 DataRelation dataRelation = new DataRelation(name, parentColumns, childColumns, createConstraints);
375 /// Performs verification on the table.
377 /// <param name="relation">The relation to check.</param>
379 protected virtual void AddCore(DataRelation relation)
381 if (relation == null)
383 //TODO: Issue a good exception message.
384 throw new ArgumentNullException();
386 else if(List.IndexOf(relation) != -1)
388 //TODO: Issue a good exception message.
389 throw new ArgumentException();
391 else if(List.Contains(relation.RelationName))
393 //TODO: Issue a good exception message.
394 throw new DuplicateNameException("A Relation named " + relation.RelationName + " already belongs to this DataSet.");
399 /// Copies the elements of the specified DataRelation array to the end of the collection.
401 /// <param name="relations">The array of DataRelation objects to add to the collection.</param>
402 public virtual void AddRange(DataRelation[] relations)
404 foreach (DataRelation relation in relations) Add(relation);
408 public virtual bool CanRemove(DataRelation relation)
414 public virtual void Clear()
419 public virtual bool Contains(string name)
421 return IndexOf(name) != -1;
424 private CollectionChangeEventArgs CreateCollectionChangeEvent (CollectionChangeAction action)
426 return new CollectionChangeEventArgs (action, this);
429 protected abstract DataSet GetDataSet();
431 public virtual int IndexOf(DataRelation relation)
433 return List.IndexOf(relation);
436 public virtual int IndexOf(string relationName)
438 return List.IndexOf(this[relationName]);
441 protected virtual void OnCollectionChanged (CollectionChangeEventArgs ccevent)
443 if (CollectionChanged != null)
444 CollectionChanged (this, ccevent);
448 protected internal virtual void OnCollectionChanging (CollectionChangeEventArgs ccevent)
450 throw new NotImplementedException ();
453 public void Remove (DataRelation relation)
455 RemoveCore (relation);
456 List.Remove (relation);
457 string name = "Relation" + index;
458 if (relation.RelationName == name)
460 OnCollectionChanged (CreateCollectionChangeEvent (CollectionChangeAction.Remove));
463 public void Remove (string name)
465 Remove ((DataRelation) List[IndexOf (name)]);
468 public void RemoveAt (int index)
470 List.RemoveAt (index);
474 protected virtual void RemoveCore(DataRelation relation)
476 // TODO: What have to be done?
479 [ResDescriptionAttribute ("Occurs whenever this collection's membership changes.")]
480 public event CollectionChangeEventHandler CollectionChanged;