// // System.Data.DataRelationCollection.cs // // Author: // Christopher Podurgiel (cpodurgiel@msn.com) // Daniel Morgan // Tim Coleman (tim@timcoleman.com) // Alan Tam Siu Lung // // (C) Chris Podurgiel // (C) 2002 Daniel Morgan // Copyright (C) Tim Coleman, 2002 // using System; using System.Collections; using System.ComponentModel; namespace System.Data { /// /// Represents the collection of DataRelation objects for this DataSet. /// [Editor] [DefaultEvent ("CollectionChanged")] [Serializable] public abstract class DataRelationCollection : InternalDataCollectionBase { /// /// Summary description for DataTableRelationCollection. /// internal class DataSetRelationCollection : DataRelationCollection { private DataSet dataSet; /// /// Initializes a new instance of the DataSetRelationCollection class. /// internal DataSetRelationCollection (DataSet dataSet) { this.dataSet = dataSet; } /// /// Gets the DataRelation object specified by name. /// public override DataRelation this [string name] { get { foreach (DataRelation dataRelation in List) if (dataRelation.RelationName == name) return dataRelation; return null; } } /// /// Gets the DataRelation object at the specified index. /// public override DataRelation this [int index] { get { return List [index] as DataRelation; } } protected override DataSet GetDataSet() { return dataSet; } /// /// Performs verification on the table. /// /// The relation to check. protected override void AddCore (DataRelation relation) { base.AddCore (relation); if (relation.ChildTable.DataSet != this.dataSet || relation.ParentTable.DataSet != this.dataSet) throw new DataException (); List.Add (relation); relation.SetDataSet (dataSet); relation.ParentTable.ChildRelations.Add (relation); relation.ChildTable.ParentRelations.Add (relation); ForeignKeyConstraint foreignKeyConstraint = null; if (relation.createConstraints) { foreignKeyConstraint = new ForeignKeyConstraint (relation.ParentColumns, relation.ChildColumns); relation.ChildTable.Constraints.Add (foreignKeyConstraint); } UniqueConstraint uniqueConstraint = null; foreach (object o in List) { if (o is UniqueConstraint) { UniqueConstraint uc = (UniqueConstraint) o; if (uc.Columns.Length == relation.ParentColumns.Length) { bool allColumnsEqual = true; for (int columnCnt = 0; columnCnt < uc.Columns.Length; ++columnCnt) { if (uc.Columns[columnCnt] != relation.ParentColumns[columnCnt]) { allColumnsEqual = false; break; } } if (allColumnsEqual) { uniqueConstraint = uc; break; } } } } relation.SetParentKeyConstraint (uniqueConstraint); relation.SetChildKeyConstraint (foreignKeyConstraint); } public override void AddRange (DataRelation[] relations) { base.AddRange (relations); } public override void Clear () { base.Clear (); } protected override void RemoveCore (DataRelation relation) { base.RemoveCore (relation); relation.SetDataSet (null); relation.ParentTable.ChildRelations.Remove (relation); relation.ChildTable.ParentRelations.Remove (relation); ForeignKeyConstraint foreignKeyConstraint = null; relation.SetParentKeyConstraint (null); relation.SetChildKeyConstraint (null); } protected override ArrayList List { get { return base.List; } } } /// /// Summary description for DataTableRelationCollection. /// internal class DataTableRelationCollection : DataRelationCollection { private DataTable dataTable; /// /// Initializes a new instance of the DataTableRelationCollection class. /// internal DataTableRelationCollection (DataTable dataTable) { this.dataTable = dataTable; } /// /// Gets the DataRelation object specified by name. /// public override DataRelation this [string name] { get { foreach (DataRelation dataRelation in List) if (dataRelation.RelationName == name) return dataRelation; return null; } } /// /// Gets the DataRelation object at the specified index. /// public override DataRelation this [int index] { get { return List [index] as DataRelation; } } protected override DataSet GetDataSet() { return dataTable.DataSet; } protected override void AddCore (DataRelation relation) { base.AddCore (relation); } protected override void RemoveCore (DataRelation relation) { base.RemoveCore (relation); } protected override ArrayList List { get { return base.List; } } } private int defaultNameIndex; private bool inTransition; /// /// Initializes a new instance of the DataRelationCollection class. /// protected DataRelationCollection () : base () { defaultNameIndex = 1; inTransition = false; } /// /// Gets the DataRelation object specified by name. /// public abstract DataRelation this[string name]{get;} /// /// Gets the DataRelation object at the specified index. /// public abstract DataRelation this[int index]{get;} #region Add Methods private string GetNextDefaultRelationName () { string defRelationName = "Relation"; for (int index = 1; Contains (defRelationName); ++index) { defRelationName = "Relation" + index; } return defRelationName; } /// /// Adds a DataRelation to the DataRelationCollection. /// /// The DataRelation to add to the collection. [MonoTODO] public void Add(DataRelation relation) { this.AddCore (relation); CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this); List.Add(relation); OnCollectionChanged(e); } /// /// Creates a relation given the parameters and adds it to the collection. The name is defaulted. /// An ArgumentException is generated if this relation already belongs to this collection or belongs to another collection. /// An InvalidConstraintException is generated if the relation can't be created based on the parameters. /// The CollectionChanged event is fired if it succeeds. /// /// parent column of relation. /// child column of relation. /// The created DataRelation. public virtual DataRelation Add(DataColumn parentColumn, DataColumn childColumn) { DataRelation dataRelation = new DataRelation(GetNextDefaultRelationName (), parentColumn, childColumn); Add(dataRelation); return dataRelation; } /// /// Creates a relation given the parameters and adds it to the collection. The name is defaulted. /// An ArgumentException is generated if this relation already belongs to this collection or belongs to another collection. /// An InvalidConstraintException is generated if the relation can't be created based on the parameters. /// The CollectionChanged event is raised if it succeeds. /// /// An array of parent DataColumn objects. /// An array of child DataColumn objects. /// The created DataRelation. public virtual DataRelation Add(DataColumn[] parentColumns, DataColumn[] childColumns) { DataRelation dataRelation = new DataRelation(GetNextDefaultRelationName (), parentColumns, childColumns); Add(dataRelation); return dataRelation; } /// /// Creates a relation given the parameters and adds it to the collection. /// An ArgumentException is generated if this relation already belongs to this collection or belongs to another collection. /// A DuplicateNameException is generated if this collection already has a relation with the same name (case insensitive). /// An InvalidConstraintException is generated if the relation can't be created based on the parameters. /// The CollectionChanged event is raised if it succeeds. /// /// The name of the relation. /// parent column of relation. /// The created DataRelation. /// public virtual DataRelation Add(string name, DataColumn parentColumn, DataColumn childColumn) { //If no name was supplied, give it a default name. if (name == null || name == "") name = GetNextDefaultRelationName (); DataRelation dataRelation = new DataRelation(name, parentColumn, childColumn); Add(dataRelation); return dataRelation; } /// /// Creates a DataRelation with the specified name, and arrays of parent and child columns, and adds it to the collection. /// /// The name of the DataRelation to create. /// An array of parent DataColumn objects. /// An array of child DataColumn objects. /// The created DataRelation. public virtual DataRelation Add(string name, DataColumn[] parentColumns, DataColumn[] childColumns) { //If no name was supplied, give it a default name. if (name == null || name == "") name = GetNextDefaultRelationName (); DataRelation dataRelation = new DataRelation(name, parentColumns, childColumns); Add(dataRelation); return dataRelation; } /// /// Creates a relation given the parameters and adds it to the collection. /// An ArgumentException is generated if this relation already belongs to this collection or belongs to another collection. /// A DuplicateNameException is generated if this collection already has a relation with the same name (case insensitive). /// An InvalidConstraintException is generated if the relation can't be created based on the parameters. /// The CollectionChanged event is raised if it succeeds. /// /// The name of the relation. /// parent column of relation. /// child column of relation. /// true to create constraints; otherwise false. (default is true) /// The created DataRelation. public virtual DataRelation Add(string name, DataColumn parentColumn, DataColumn childColumn, bool createConstraints) { //If no name was supplied, give it a default name. if (name == null || name == "") name = GetNextDefaultRelationName (); DataRelation dataRelation = new DataRelation(name, parentColumn, childColumn, createConstraints); Add(dataRelation); return dataRelation; } /// /// Creates a DataRelation with the specified name, arrays of parent and child columns, /// and value specifying whether to create a constraint, and adds it to the collection. /// /// The name of the DataRelation to create. /// An array of parent DataColumn objects. /// An array of child DataColumn objects. /// true to create a constraint; otherwise false. /// The created DataRelation. public virtual DataRelation Add(string name, DataColumn[] parentColumns, DataColumn[] childColumns, bool createConstraints) { //If no name was supplied, give it a default name. if (name == null || name == "") name = GetNextDefaultRelationName (); DataRelation dataRelation = new DataRelation(name, parentColumns, childColumns, createConstraints); Add(dataRelation); return dataRelation; } #endregion /// /// Performs verification on the table. /// /// The relation to check. [MonoTODO] protected virtual void AddCore(DataRelation relation) { if (relation == null) { //TODO: Issue a good exception message. throw new ArgumentNullException(); } else if(List.IndexOf(relation) != -1) { //TODO: Issue a good exception message. throw new ArgumentException(); } else if(List.Contains(relation.RelationName)) { //TODO: Issue a good exception message. throw new DuplicateNameException("A Relation named " + relation.RelationName + " already belongs to this DataSet."); } } /// /// Copies the elements of the specified DataRelation array to the end of the collection. /// /// The array of DataRelation objects to add to the collection. public virtual void AddRange(DataRelation[] relations) { foreach (DataRelation relation in relations) Add(relation); } [MonoTODO] public virtual bool CanRemove(DataRelation relation) { //TODO: Implement. return false; } public virtual void Clear() { List.Clear(); } public virtual bool Contains(string name) { return IndexOf(name) != -1; } private CollectionChangeEventArgs CreateCollectionChangeEvent (CollectionChangeAction action) { return new CollectionChangeEventArgs (action, this); } protected abstract DataSet GetDataSet(); public virtual int IndexOf(DataRelation relation) { return List.IndexOf(relation); } public virtual int IndexOf(string relationName) { return List.IndexOf(this[relationName]); } protected virtual void OnCollectionChanged (CollectionChangeEventArgs ccevent) { if (CollectionChanged != null) CollectionChanged (this, ccevent); } [MonoTODO] protected internal virtual void OnCollectionChanging (CollectionChangeEventArgs ccevent) { throw new NotImplementedException (); } public void Remove (DataRelation relation) { RemoveCore (relation); List.Remove (relation); OnCollectionChanged (CreateCollectionChangeEvent (CollectionChangeAction.Remove)); } public void Remove (string name) { Remove ((DataRelation) List[IndexOf (name)]); } public void RemoveAt (int index) { List.RemoveAt (index); } [MonoTODO] protected virtual void RemoveCore(DataRelation relation) { // TODO: What have to be done? } [ResDescriptionAttribute ("Occurs whenever this collection's membership changes.")] public event CollectionChangeEventHandler CollectionChanged; } }