// Copyright (C) Tim Coleman, 2002
//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
using System;
using System.Collections;
using System.ComponentModel;
/// <summary>
/// Represents the collection of DataRelation objects for this DataSet.
/// </summary>
- [Editor]
+ [Editor ("Microsoft.VSDesigner.Data.Design.DataRelationCollectionEditor, " + Consts.AssemblyMicrosoft_VSDesigner,
+ "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
[DefaultEvent ("CollectionChanged")]
+ [DefaultProperty ("Table")]
+#if !NET_2_0
[Serializable]
- public abstract class DataRelationCollection : InternalDataCollectionBase
- {
+#endif
+ public abstract class DataRelationCollection : InternalDataCollectionBase {
/// <summary>
/// Summary description for DataTableRelationCollection.
/// </summary>
- internal class DataSetRelationCollection : DataRelationCollection
- {
+ internal class DataSetRelationCollection : DataRelationCollection {
private DataSet dataSet;
-
+ DataRelation [] mostRecentRelations;
+
/// <summary>
/// Initializes a new instance of the DataSetRelationCollection class.
/// </summary>
this.dataSet = dataSet;
}
- /// <summary>
- /// Gets the DataRelation object specified by name.
- /// </summary>
- public override DataRelation this [string name]
- {
- get {
- foreach (DataRelation dataRelation in List)
- if (dataRelation.RelationName == name) return dataRelation;
- return null;
- }
- }
-
- /// <summary>
- /// Gets the DataRelation object at the specified index.
- /// </summary>
- public override DataRelation this [int index]
- {
- get {
- return List [index] as DataRelation;
- }
- }
-
- protected override DataSet GetDataSet()
+ protected override DataSet GetDataSet ()
{
return dataSet;
}
/// <param name="relation">The relation to check.</param>
protected override void AddCore (DataRelation relation)
{
+ if (relation.ChildTable.DataSet != dataSet || relation.ParentTable.DataSet != dataSet)
+ throw new DataException ();
+
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 ();
+ relation.SetDataSet (dataSet);
+ relation.UpdateConstraints ();
}
protected override void RemoveCore (DataRelation relation)
relation.SetDataSet (null);
relation.ParentTable.ChildRelations.Remove (relation);
relation.ChildTable.ParentRelations.Remove (relation);
- ForeignKeyConstraint foreignKeyConstraint = null;
relation.SetParentKeyConstraint (null);
relation.SetChildKeyConstraint (null);
}
+ public override void AddRange (DataRelation [] relations)
+ {
+ if (relations == null)
+ return;
+
+ if (dataSet != null && dataSet.InitInProgress){
+ mostRecentRelations = relations;
+ return;
+ }
+
+ foreach (DataRelation rel in relations){
+ if (rel == null)
+ continue;
+ Add (rel);
+ }
+ }
+
+ internal override void PostAddRange ()
+ {
+ if (mostRecentRelations == null)
+ return;
+
+ foreach (DataRelation rel in mostRecentRelations){
+ if (rel == null)
+ continue;
+ if (rel.InitInProgress)
+ rel.FinishInit (dataSet);
+ Add (rel);
+ }
+ mostRecentRelations = null;
+ }
+
protected override ArrayList List {
+ get { return base.List; }
+ }
+
+ public override DataRelation this [string name] {
get {
- return base.List;
+ int index = IndexOf (name, true);
+ return index < 0 ? null : (DataRelation) List [index];
+ }
+ }
+
+ /// <summary>
+ /// Gets the DataRelation object at the specified index.
+ /// </summary>
+ public override DataRelation this [int index] {
+ get {
+ if (index < 0 || index >= List.Count)
+ throw new IndexOutOfRangeException (String.Format ("Cannot find relation {0}.", index));
+
+ return (DataRelation) List [index];
}
}
}
/// <summary>
/// Summary description for DataTableRelationCollection.
/// </summary>
- internal class DataTableRelationCollection : DataRelationCollection
- {
+ internal class DataTableRelationCollection : DataRelationCollection {
private DataTable dataTable;
-
+
/// <summary>
/// Initializes a new instance of the DataTableRelationCollection class.
/// </summary>
this.dataTable = dataTable;
}
- /// <summary>
- /// Gets the DataRelation object specified by name.
- /// </summary>
- public override DataRelation this [string name]
+ protected override DataSet GetDataSet ()
{
+ return dataTable.DataSet;
+ }
+
+ public override DataRelation this [string name] {
get {
- foreach (DataRelation dataRelation in List)
- if (dataRelation.RelationName == name) return dataRelation;
- return null;
+ int index = IndexOf (name, true);
+ return index < 0 ? null : (DataRelation) List [index];
}
}
/// <summary>
/// Gets the DataRelation object at the specified index.
/// </summary>
- public override DataRelation this [int index]
- {
+ public override DataRelation this [int index] {
get {
- return List [index] as DataRelation;
- }
- }
+ if (index < 0 || index >= List.Count)
+ throw new IndexOutOfRangeException (String.Format ("Cannot find relation {0}.", index));
- protected override DataSet GetDataSet()
- {
- return dataTable.DataSet;
+ return (DataRelation) List [index];
+ }
}
+ /// <summary>
+ /// Performs verification on the table.
+ /// </summary>
+ /// <param name="relation">The relation to check.</param>
protected override void AddCore (DataRelation relation)
{
+ if (dataTable.ParentRelations == this && relation.ChildTable != dataTable)
+ throw new ArgumentException ("Cannot add a relation to this table's " +
+ "ParentRelations where this table is not" +
+ " the Child table.");
+
+ if (dataTable.ChildRelations == this && relation.ParentTable != dataTable)
+ throw new ArgumentException("Cannot add a relation to this table's " +
+ "ChildRelations where this table is not" +
+ " the Parent table.");
+
+ dataTable.DataSet.Relations.Add (relation);
base.AddCore (relation);
- GetDataSet ().Relations.Add (relation);
}
protected override void RemoveCore (DataRelation relation)
{
+ relation.DataSet.Relations.Remove(relation);
base.RemoveCore (relation);
- GetDataSet ().Relations.Remove (relation);
}
protected override ArrayList List {
- get {
- return base.List;
- }
+ get { return base.List; }
}
}
- private int defaultNameIndex;
- private bool inTransition;
-
+ private DataRelation inTransition;
+ int index;
+
+
/// <summary>
/// Initializes a new instance of the DataRelationCollection class.
/// </summary>
- protected DataRelationCollection ()
- : base ()
+ protected DataRelationCollection ()
{
- defaultNameIndex = 1;
- inTransition = false;
+ inTransition = null;
}
/// <summary>
/// Gets the DataRelation object specified by name.
/// </summary>
- public abstract DataRelation this[string name]{get;}
+ public abstract DataRelation this [string name] {
+ get;
+ }
/// <summary>
/// Gets the DataRelation object at the specified index.
/// </summary>
- public abstract DataRelation this[int index]{get;}
+ public abstract DataRelation this [int index] {
+ get;
+ }
+
-
#region Add Methods
private string GetNextDefaultRelationName ()
{
- string defRelationName = "Relation";
- for (int index = 1; Contains (defRelationName); ++index) {
+ int index = 1;
+ string defRelationName = "Relation" + index;
+ for (; Contains (defRelationName); ++index)
defRelationName = "Relation" + index;
- }
return defRelationName;
}
/// Adds a DataRelation to the DataRelationCollection.
/// </summary>
/// <param name="relation">The DataRelation to add to the collection.</param>
- [MonoTODO]
- public void Add(DataRelation relation)
+ public void Add (DataRelation relation)
{
- this.AddCore (relation);
- CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
- List.Add(relation);
- OnCollectionChanged(e);
+ // To prevent endless recursion
+ if (inTransition == relation)
+ return;
+
+ inTransition = relation;
+
+ try {
+ CollectionChangeEventArgs e = new CollectionChangeEventArgs (CollectionChangeAction.Add, this);
+ OnCollectionChanging (e);
+
+ this.AddCore (relation);
+ if (relation.RelationName == string.Empty)
+ relation.RelationName = GenerateRelationName ();
+
+ relation.ParentTable.ResetPropertyDescriptorsCache ();
+ relation.ChildTable.ResetPropertyDescriptorsCache ();
+
+ e = new CollectionChangeEventArgs (CollectionChangeAction.Add, this);
+ OnCollectionChanged (e);
+ } finally {
+ inTransition = null;
+ }
+ }
+
+ private string GenerateRelationName ()
+ {
+ index++;
+ return "Relation" + index;
}
/// <summary>
/// <param name="parentColumn">parent column of relation.</param>
/// <param name="childColumn">child column of relation.</param>
/// <returns>The created DataRelation.</returns>
- public virtual DataRelation Add(DataColumn parentColumn, DataColumn childColumn)
- {
- DataRelation dataRelation = new DataRelation(GetNextDefaultRelationName (), parentColumn, childColumn);
- Add(dataRelation);
+ public virtual DataRelation Add (DataColumn parentColumn, DataColumn childColumn)
+ {
+ DataRelation dataRelation = new DataRelation (GetNextDefaultRelationName (), parentColumn, childColumn);
+ Add (dataRelation);
return dataRelation;
}
/// <param name="parentColumns">An array of parent DataColumn objects.</param>
/// <param name="childColumns">An array of child DataColumn objects.</param>
/// <returns>The created DataRelation.</returns>
- public virtual DataRelation Add(DataColumn[] parentColumns, DataColumn[] childColumns)
+ public virtual DataRelation Add (DataColumn [] parentColumns, DataColumn [] childColumns)
{
- DataRelation dataRelation = new DataRelation(GetNextDefaultRelationName (), parentColumns, childColumns);
- Add(dataRelation);
+ DataRelation dataRelation = new DataRelation (GetNextDefaultRelationName (), parentColumns, childColumns);
+ Add (dataRelation);
return dataRelation;
}
/// <param name="parentColumn">parent column of relation.</param>
/// <returns>The created DataRelation.</returns>
/// <returns></returns>
- public virtual DataRelation Add(string name, DataColumn parentColumn, DataColumn childColumn)
+ 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 ();
+ if (name == null || name == "")
+ name = GetNextDefaultRelationName ();
- DataRelation dataRelation = new DataRelation(name, parentColumn, childColumn);
- Add(dataRelation);
+ DataRelation dataRelation = new DataRelation (name, parentColumn, childColumn);
+ Add (dataRelation);
return dataRelation;
}
/// <param name="parentColumns">An array of parent DataColumn objects.</param>
/// <param name="childColumns">An array of child DataColumn objects.</param>
/// <returns>The created DataRelation.</returns>
- public virtual DataRelation Add(string name, DataColumn[] parentColumns, DataColumn[] childColumns)
+ 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 ();
+ if (name == null || name == "")
+ name = GetNextDefaultRelationName ();
- DataRelation dataRelation = new DataRelation(name, parentColumns, childColumns);
- Add(dataRelation);
+ DataRelation dataRelation = new DataRelation (name, parentColumns, childColumns);
+ Add (dataRelation);
return 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 ();
+ if (name == null || name == "")
+ name = GetNextDefaultRelationName ();
- DataRelation dataRelation = new DataRelation(name, parentColumn, childColumn, createConstraints);
- Add(dataRelation);
+ DataRelation dataRelation = new DataRelation (name, parentColumn, childColumn, createConstraints);
+ Add (dataRelation);
return dataRelation;
}
/// <summary>
- /// Creates a DataRelation with the specified name, arrays of parent and child columns,
+ /// 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.
/// </summary>
/// <param name="name">The name of the DataRelation to create.</param>
/// <param name="childColumns">An array of child DataColumn objects.</param>
/// <param name="createConstraints">true to create a constraint; otherwise false.</param>
/// <returns>The created DataRelation.</returns>
- public virtual DataRelation Add(string name, DataColumn[] parentColumns, DataColumn[] childColumns, bool createConstraints)
+ 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 ();
+ if (name == null || name == "")
+ name = GetNextDefaultRelationName ();
- DataRelation dataRelation = new DataRelation(name, parentColumns, childColumns, createConstraints);
- Add(dataRelation);
+ DataRelation dataRelation = new DataRelation (name, parentColumns, childColumns, createConstraints);
+ Add (dataRelation);
return dataRelation;
}
#endregion
-
+
/// <summary>
- /// Performs verification on the table.
+ /// Adds to the list
/// </summary>
/// <param name="relation">The relation to check.</param>
- [MonoTODO]
- protected virtual void AddCore(DataRelation relation)
+ protected virtual void AddCore (DataRelation relation)
{
if (relation == null)
- {
//TODO: Issue a good exception message.
throw new ArgumentNullException();
- }
- else if(List.IndexOf(relation) != -1)
- {
+
+ if(List.IndexOf (relation) != -1)
//TODO: Issue a good exception message.
throw new ArgumentException();
+
+ // check if the collection has a relation with the same name.
+ int tmp = IndexOf (relation.RelationName);
+ // if we found a relation with same name we have to check
+ // that it is the same case.
+ // indexof can return a table with different case letters.
+ if (tmp != -1 && relation.RelationName == this [tmp].RelationName)
+ throw new DuplicateNameException("A DataRelation named '" + relation.RelationName + "' already belongs to this DataSet.");
+
+ // check whether the relation exists between the columns already
+ foreach (DataRelation rel in this) {
+ // compare child columns
+ bool differs = false;
+ foreach (DataColumn current in relation.ChildColumns) {
+ bool exists = false;
+ foreach (DataColumn col in rel.ChildColumns) {
+ if (col == current) {
+ exists = true;
+ break;
+ }
+ }
+ if (!exists) {
+ differs = true;
+ break;
+ }
+ }
+
+ if (! differs) {
+ // compare parent columns
+ differs = false;
+ foreach (DataColumn current in relation.ParentColumns) {
+ bool exists = false;
+ foreach (DataColumn col in rel.ParentColumns) {
+ if (col == current) {
+ exists = true;
+ break;
+ }
+ }
+ if (!exists) {
+ differs = true;
+ break;
+ }
+ }
+
+ if (! differs)
+ throw new ArgumentException ("A relation already exists for these child columns");
+ }
}
- 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.");
- }
+
+ // Add to collection
+ List.Add (relation);
}
/// <summary>
/// Copies the elements of the specified DataRelation array to the end of the collection.
/// </summary>
/// <param name="relations">The array of DataRelation objects to add to the collection.</param>
- public virtual void AddRange(DataRelation[] relations)
+ public virtual void AddRange (DataRelation[] relations)
{
- foreach (DataRelation relation in relations) Add(relation);
+ if (relations == null)
+ return;
+
+ foreach (DataRelation relation in relations)
+ Add (relation);
}
- [MonoTODO]
- public virtual bool CanRemove(DataRelation relation)
+#if NET_2_0
+ public void CopyTo (DataRelation [] array, int index)
{
- //TODO: Implement.
- return false;
+ CopyTo ((Array) array, index);
}
+#endif
- public virtual void Clear()
+ internal virtual void PostAddRange ()
{
- List.Clear();
}
- public virtual bool Contains(string name)
+ public virtual bool CanRemove (DataRelation relation)
{
- return IndexOf(name) != -1;
+ if (relation == null || !GetDataSet ().Equals (relation.DataSet))
+ return false;
+
+ // check if the relation doesnot belong to this collection
+ int tmp = IndexOf (relation.RelationName);
+ return tmp != -1 && relation.RelationName == this [tmp].RelationName;
+ }
+
+ public virtual void Clear ()
+ {
+ for (int i = 0; i < Count; i++)
+ Remove (this [i]);
+
+ List.Clear ();
+ }
+
+ public virtual bool Contains (string name)
+ {
+ DataSet tmpDataSet = GetDataSet ();
+ if (tmpDataSet != null) {
+ DataRelation tmpRelation = tmpDataSet.Relations [name];
+ if (tmpRelation != null)
+ return true;
+ }
+ return (-1 != IndexOf (name, false));
}
private CollectionChangeEventArgs CreateCollectionChangeEvent (CollectionChangeAction action)
return new CollectionChangeEventArgs (action, this);
}
- protected abstract DataSet GetDataSet();
+ protected abstract DataSet GetDataSet ();
- public virtual int IndexOf(DataRelation relation)
+ public virtual int IndexOf (DataRelation relation)
{
- return List.IndexOf(relation);
+ return List.IndexOf (relation);
}
- public virtual int IndexOf(string relationName)
+ public virtual int IndexOf (string relationName)
{
- return List.IndexOf(this[relationName]);
+ return IndexOf (relationName, false);
+ }
+
+ private int IndexOf (string name, bool error)
+ {
+ int count = 0, match = -1;
+ for (int i = 0; i < List.Count; i++) {
+ String name2 = ((DataRelation) List[i]).RelationName;
+ if (String.Compare (name, name2, true) == 0) {
+ if (String.Compare (name, name2, false) == 0)
+ return i;
+ match = i;
+ count++;
+ }
+ }
+ if (count == 1)
+ return match;
+ if (count > 1 && error)
+ throw new ArgumentException ("There is no match for the name in the same case and there are multiple matches in different case.");
+ return -1;
}
protected virtual void OnCollectionChanged (CollectionChangeEventArgs ccevent)
CollectionChanged (this, ccevent);
}
- [MonoTODO]
- protected internal virtual void OnCollectionChanging (CollectionChangeEventArgs ccevent)
+ protected virtual void OnCollectionChanging (CollectionChangeEventArgs ccevent)
{
- throw new NotImplementedException ();
+ // LAME Spec: No associated events and it doesn't update CollectionChanged
+ // event too as specified in MSDN
+ // throw new NotImplementedException ();
}
public void Remove (DataRelation relation)
{
- RemoveCore (relation);
- List.Remove (relation);
- OnCollectionChanged (CreateCollectionChangeEvent (CollectionChangeAction.Remove));
+ // To prevent endless recursion
+ if (inTransition == relation)
+ return;
+
+ inTransition = relation;
+
+ if (relation == null)
+ return;
+
+ try {
+ // check if the list doesnot contains this relation.
+ if (!(List.Contains (relation)))
+ throw new ArgumentException ("Relation doesnot belong to this Collection.");
+
+ OnCollectionChanging (CreateCollectionChangeEvent (CollectionChangeAction.Remove));
+
+ RemoveCore (relation);
+ string name = "Relation" + index;
+ if (relation.RelationName == name)
+ index--;
+
+ OnCollectionChanged (CreateCollectionChangeEvent (CollectionChangeAction.Remove));
+ } finally {
+ inTransition = null;
+ }
}
public void Remove (string name)
{
- Remove ((DataRelation) List[IndexOf (name)]);
+ DataRelation relation = this [name];
+ if (relation == null)
+ throw new ArgumentException ("Relation doesnot belong to this Collection.");
+ Remove (relation);
}
public void RemoveAt (int index)
{
- List.RemoveAt (index);
+ DataRelation relation = this [index];
+ if (relation == null)
+ throw new IndexOutOfRangeException (String.Format ("Cannot find relation {0}", index));
+ Remove (relation);
}
- [MonoTODO]
- protected virtual void RemoveCore(DataRelation relation)
+ protected virtual void RemoveCore (DataRelation relation)
{
- // TODO: What have to be done?
+ // Remove from collection
+ List.Remove (relation);
}
+ #region Events
+
[ResDescriptionAttribute ("Occurs whenever this collection's membership changes.")]
public event CollectionChangeEventHandler CollectionChanged;
+
+ #endregion
}
}