Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / Data / System / Data / ConstraintCollection.cs / 1 / ConstraintCollection.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //[....] //[....] //----------------------------------------------------------------------------- namespace System.Data { using System; using System.Diagnostics; using System.Collections; using System.ComponentModel; ////// [ DefaultEvent("CollectionChanged"), Editor("Microsoft.VSDesigner.Data.Design.ConstraintsCollectionEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing), ] #if WINFSInternalOnly internal #else public #endif sealed class ConstraintCollection : InternalDataCollectionBase { // WebData 111752 private readonly DataTable table; // private Constraint[] constraints = new Constraint[2]; private readonly ArrayList list = new ArrayList(); private int defaultNameIndex = 1; private CollectionChangeEventHandler onCollectionChanged; private Constraint[] delayLoadingConstraints; private bool fLoadForeignKeyConstraintsOnly = false; ///Represents a collection of constraints for a ////// . /// ConstraintCollection constructor. Used only by DataTable. /// internal ConstraintCollection(DataTable table) { this.table = table; } ////// protected override ArrayList List { get { return list; } } ///Gets the list of objects contained by the collection. ////// public Constraint this[int index] { get { if (index >= 0 && index < List.Count) { return(Constraint) List[index]; } throw ExceptionBuilder.ConstraintOutOfRange(index); } } ///Gets the ////// from the collection at the specified index. /// The DataTable with which this ConstraintCollection is associated /// internal DataTable Table { get { return table; } } ////// public Constraint this[string name] { get { int index = InternalIndexOf(name); if (index == -2) { throw ExceptionBuilder.CaseInsensitiveNameConflict(name); } return (index < 0) ? null : (Constraint)List[index]; } } ///Gets the ///from the collection with the specified name. /// public void Add(Constraint constraint) { Add(constraint, true); } // To add foreign key constraint without adding any unique constraint for internal use. Main purpose : Binary Remoting internal void Add(Constraint constraint, bool addUniqueWhenAddingForeign) { if (constraint == null) throw ExceptionBuilder.ArgumentNull("constraint"); // It is an error if we find an equivalent constraint already in collection if (FindConstraint(constraint) != null) { throw ExceptionBuilder.DuplicateConstraint(FindConstraint(constraint).ConstraintName); } if (1 < table.NestedParentRelations.Length) { if (!AutoGenerated(constraint)) { throw ExceptionBuilder.CantAddConstraintToMultipleNestedTable(table.TableName); } } if (constraint is UniqueConstraint) { if (((UniqueConstraint)constraint).bPrimaryKey) { if (Table.primaryKey != null) { throw ExceptionBuilder.AddPrimaryKeyConstraint(); } } AddUniqueConstraint((UniqueConstraint)constraint); } else if (constraint is ForeignKeyConstraint) { ForeignKeyConstraint fk = (ForeignKeyConstraint)constraint; if (addUniqueWhenAddingForeign) { UniqueConstraint key = fk.RelatedTable.Constraints.FindKeyConstraint(fk.RelatedColumnsReference); if (key == null) { if (constraint.ConstraintName.Length == 0) constraint.ConstraintName = AssignName(); else RegisterName(constraint.ConstraintName); key = new UniqueConstraint(fk.RelatedColumnsReference); fk.RelatedTable.Constraints.Add(key); } } AddForeignKeyConstraint((ForeignKeyConstraint)constraint); } BaseAdd(constraint); ArrayAdd(constraint); OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Add, constraint)); if (constraint is UniqueConstraint) { if (((UniqueConstraint)constraint).bPrimaryKey) { Table.PrimaryKey = ((UniqueConstraint)constraint).ColumnsReference; } } } ////// Adds the constraint to the collection. ////// public Constraint Add(string name, DataColumn[] columns, bool primaryKey) { UniqueConstraint constraint = new UniqueConstraint(name, columns); Add(constraint); if (primaryKey) Table.PrimaryKey = columns; return constraint; } ///Constructs a new ///using the /// specified array of /// objects and adds it to the collection. /// public Constraint Add(string name, DataColumn column, bool primaryKey) { UniqueConstraint constraint = new UniqueConstraint(name, column); Add(constraint); if (primaryKey) Table.PrimaryKey = constraint.ColumnsReference; return constraint; } ///Constructs a new ///using the /// specified and adds it to the collection. /// public Constraint Add(string name, DataColumn primaryKeyColumn, DataColumn foreignKeyColumn) { ForeignKeyConstraint constraint = new ForeignKeyConstraint(name, primaryKeyColumn, foreignKeyColumn); Add(constraint); return constraint; } ////// Constructs a new ////// with the /// specified parent and child /// columns and adds the constraint to the collection. /// public Constraint Add(string name, DataColumn[] primaryKeyColumns, DataColumn[] foreignKeyColumns) { ForeignKeyConstraint constraint = new ForeignKeyConstraint(name, primaryKeyColumns, foreignKeyColumns); Add(constraint); return constraint; } public void AddRange(Constraint[] constraints ) { if (table.fInitInProgress) { delayLoadingConstraints = constraints; fLoadForeignKeyConstraintsOnly = false; return; } if (constraints != null) { foreach(Constraint constr in constraints) { if (constr != null) { Add(constr); } } } } private void AddUniqueConstraint(UniqueConstraint constraint) { DataColumn[] columns = constraint.ColumnsReference; for (int i = 0; i < columns.Length; i++) { if (columns[i].Table != this.table) { throw ExceptionBuilder.ConstraintForeignTable(); } } constraint.ConstraintIndexInitialize(); if (!constraint.CanEnableConstraint()) { constraint.ConstraintIndexClear(); throw ExceptionBuilder.UniqueConstraintViolation(); } } private void AddForeignKeyConstraint(ForeignKeyConstraint constraint) { if (!constraint.CanEnableConstraint()) { throw ExceptionBuilder.ConstraintParentValues(); } constraint.CheckCanAddToCollection(this); } private bool AutoGenerated(Constraint constraint) { ForeignKeyConstraint fk = (constraint as ForeignKeyConstraint); if (null != fk) { return XmlTreeGen.AutoGenerated(fk, false); } else { UniqueConstraint unique = (UniqueConstraint) constraint; return XmlTreeGen.AutoGenerated(unique); } } ///Constructs a new ///with the specified parent columns and /// child columns and adds the constraint to the collection. /// public event CollectionChangeEventHandler CollectionChanged { add { onCollectionChanged += value; } remove { onCollectionChanged -= value; } } ///Occurs when the ///is changed through additions or /// removals. /// Adds the constraint to the constraints array. /// private void ArrayAdd(Constraint constraint) { Debug.Assert(constraint != null, "Attempt to add null constraint to constraint array"); List.Add(constraint); } private void ArrayRemove(Constraint constraint) { List.Remove(constraint); } ////// Creates a new default name. /// internal string AssignName() { string newName = MakeName(defaultNameIndex); defaultNameIndex++; return newName; } ////// Does verification on the constraint and it's name. /// An ArgumentNullException is thrown if this constraint is null. An ArgumentException is thrown if this constraint /// already belongs to this collection, belongs to another collection. /// A DuplicateNameException is thrown if this collection already has a constraint with the same /// name (case insensitive). /// private void BaseAdd(Constraint constraint) { if (constraint == null) throw ExceptionBuilder.ArgumentNull("constraint"); if (constraint.ConstraintName.Length == 0) constraint.ConstraintName = AssignName(); else RegisterName(constraint.ConstraintName); constraint.InCollection = true; } ////// BaseGroupSwitch will intelligently remove and add tables from the collection. /// private void BaseGroupSwitch(Constraint[] oldArray, int oldLength, Constraint[] newArray, int newLength) { // We're doing a smart diff of oldArray and newArray to find out what // should be removed. We'll pass through oldArray and see if it exists // in newArray, and if not, do remove work. newBase is an opt. in case // the arrays have similar prefixes. int newBase = 0; for (int oldCur = 0; oldCur < oldLength; oldCur++) { bool found = false; for (int newCur = newBase; newCur < newLength; newCur++) { if (oldArray[oldCur] == newArray[newCur]) { if (newBase == newCur) { newBase++; } found = true; break; } } if (!found) { // This means it's in oldArray and not newArray. Remove it. BaseRemove(oldArray[oldCur]); List.Remove(oldArray[oldCur]); } } // Now, let's pass through news and those that don't belong, add them. for (int newCur = 0; newCur < newLength; newCur++) { if (!newArray[newCur].InCollection) BaseAdd(newArray[newCur]); List.Add(newArray[newCur]); } } ////// Does verification on the constraint and it's name. /// An ArgumentNullException is thrown if this constraint is null. An ArgumentException is thrown /// if this constraint doesn't belong to this collection or if this constraint is part of a relationship. /// private void BaseRemove(Constraint constraint) { if (constraint == null) { throw ExceptionBuilder.ArgumentNull("constraint"); } if (constraint.Table != table) { throw ExceptionBuilder.ConstraintRemoveFailed(); } UnregisterName(constraint.ConstraintName); constraint.InCollection = false; if (constraint is UniqueConstraint) { for (int i = 0; i < Table.ChildRelations.Count; i++) { DataRelation rel = Table.ChildRelations[i]; if (rel.ParentKeyConstraint == constraint) rel.SetParentKeyConstraint(null); } ((UniqueConstraint)constraint).ConstraintIndexClear(); } else if (constraint is ForeignKeyConstraint) { for (int i = 0; i < Table.ParentRelations.Count; i++) { DataRelation rel = Table.ParentRelations[i]; if (rel.ChildKeyConstraint == constraint) rel.SetChildKeyConstraint(null); } } } ////// // PUBLIC because called by design-time... need to consider this. public bool CanRemove(Constraint constraint) { return CanRemove(constraint, /*fThrowException:*/false); } internal bool CanRemove(Constraint constraint, bool fThrowException) { return constraint.CanBeRemovedFromCollection(this, fThrowException); } ///Indicates if a ///can be removed. /// public void Clear() { if (table != null) { table.PrimaryKey = null; for (int i = 0; i < table.ParentRelations.Count; i++) { table.ParentRelations[i].SetChildKeyConstraint(null); } for (int i = 0; i < table.ChildRelations.Count; i++) { table.ChildRelations[i].SetParentKeyConstraint(null); } } if (table.fInitInProgress && delayLoadingConstraints != null) { delayLoadingConstraints = null; fLoadForeignKeyConstraintsOnly = false; } int oldLength = List.Count; Constraint[] constraints = new Constraint[List.Count]; List.CopyTo(constraints, 0); try { // this will smartly add and remove the appropriate tables. BaseGroupSwitch(constraints, oldLength, null, 0); } catch (Exception e) { // if (Common.ADP.IsCatchableOrSecurityExceptionType(e)) { // something messed up. restore to original state. BaseGroupSwitch(null, 0, constraints, oldLength); List.Clear(); for (int i = 0; i < oldLength; i++) List.Add(constraints[i]); } throw; } List.Clear(); OnCollectionChanged(RefreshEventArgs); } ///Clears the collection of any ////// objects. /// public bool Contains(string name) { return (InternalIndexOf(name) >= 0); } internal bool Contains(string name, bool caseSensitive) { if (!caseSensitive) return Contains(name); int index = InternalIndexOf(name); if (index<0) return false; return (name == ((Constraint) List[index]).ConstraintName); } public void CopyTo(Constraint[] array, int index) { if (array==null) throw ExceptionBuilder.ArgumentNull("array"); if (index < 0) throw ExceptionBuilder.ArgumentOutOfRange("index"); if (array.Length - index < list.Count) throw ExceptionBuilder.InvalidOffsetLength(); for(int i = 0; i < list.Count; ++i) { array[index + i] = (Constraint)list[i]; } } ///Indicates whether the ///, specified by name, exists in the collection. /// Returns a matching constriant object. /// internal Constraint FindConstraint(Constraint constraint) { int constraintCount = List.Count; for (int i = 0; i < constraintCount; i++) { if (((Constraint)List[i]).Equals(constraint)) return(Constraint)List[i]; } return null; } ////// Returns a matching constriant object. /// internal UniqueConstraint FindKeyConstraint(DataColumn[] columns) { int constraintCount = List.Count; for (int i = 0; i < constraintCount; i++) { UniqueConstraint constraint = (List[i] as UniqueConstraint); if ((null != constraint) && CompareArrays(constraint.Key.ColumnsReference, columns)) { return constraint; } } return null; } ////// Returns a matching constriant object. /// internal UniqueConstraint FindKeyConstraint(DataColumn column) { int constraintCount = List.Count; for (int i = 0; i < constraintCount; i++) { UniqueConstraint constraint = (List[i] as UniqueConstraint); if ((null != constraint) && (constraint.Key.ColumnsReference.Length == 1) && (constraint.Key.ColumnsReference[0] == column)) return constraint; } return null; } ////// Returns a matching constriant object. /// internal ForeignKeyConstraint FindForeignKeyConstraint(DataColumn[] parentColumns, DataColumn[] childColumns) { int constraintCount = List.Count; for (int i = 0; i < constraintCount; i++) { ForeignKeyConstraint constraint = (List[i] as ForeignKeyConstraint); if ((null != constraint) && CompareArrays(constraint.ParentKey.ColumnsReference, parentColumns) && CompareArrays(constraint.ChildKey.ColumnsReference, childColumns)) return constraint; } return null; } private static bool CompareArrays(DataColumn[] a1, DataColumn[] a2) { Debug.Assert(a1 != null && a2 != null, "Invalid Arguments"); if (a1.Length != a2.Length) return false; int i, j; for (i=0; i/// Returns the index of the specified /// public int IndexOf(Constraint constraint) { if (null != constraint) { int count = Count; for (int i = 0; i < count; ++i) { if (constraint == (Constraint) List[i]) return i; } // didnt find the constraint } return -1; } ///. /// public int IndexOf(string constraintName) { int index = InternalIndexOf(constraintName); return (index < 0) ? -1 : index; } // Return value: // >= 0: find the match // -1: No match // -2: At least two matches with different cases internal int InternalIndexOf(string constraintName) { int cachedI = -1; if ((null != constraintName) && (0 < constraintName.Length)) { int constraintCount = List.Count; int result = 0; for (int i = 0; i < constraintCount; i++) { Constraint constraint = (Constraint) List[i]; result = NamesEqual(constraint.ConstraintName, constraintName, false, table.Locale); if (result == 1) return i; if (result == -1) cachedI = (cachedI == -1) ? i : -2; } } return cachedI; } ///Returns the index of the ///, specified by name. /// Makes a default name with the given index. e.g. Constraint1, Constraint2, ... Constrainti /// private string MakeName(int index) { if (1 == index) { return "Constraint1"; } return "Constraint" + index.ToString(System.Globalization.CultureInfo.InvariantCulture); } ////// private void OnCollectionChanged(CollectionChangeEventArgs ccevent) { if (onCollectionChanged != null) { onCollectionChanged(this, ccevent); } } ///Raises the ///event. /// Registers this name as being used in the collection. Will throw an ArgumentException /// if the name is already being used. Called by Add, All property, and Constraint.ConstraintName property. /// if the name is equivalent to the next default name to hand out, we increment our defaultNameIndex. /// internal void RegisterName(string name) { Debug.Assert (name != null); int constraintCount = List.Count; for (int i = 0; i < constraintCount; i++) { if (NamesEqual(name, ((Constraint)List[i]).ConstraintName, true, table.Locale) != 0) { throw ExceptionBuilder.DuplicateConstraintName(((Constraint)List[i]).ConstraintName); } } if (NamesEqual(name, MakeName(defaultNameIndex), true, table.Locale) != 0) { defaultNameIndex++; } } ////// public void Remove(Constraint constraint) { if (constraint == null) throw ExceptionBuilder.ArgumentNull("constraint"); // this will throw an exception if it can't be removed, otherwise indicates // whether we need to remove it from the collection. if (CanRemove(constraint, true)) { // constraint can be removed BaseRemove(constraint); ArrayRemove(constraint); if (constraint is UniqueConstraint && ((UniqueConstraint)constraint).IsPrimaryKey) { Table.PrimaryKey = null; } OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Remove, constraint)); } } ////// Removes the specified ////// from the collection. /// public void RemoveAt(int index) { Constraint c = this[index]; if (c == null) throw ExceptionBuilder.ConstraintOutOfRange(index); Remove(c); } ///Removes the constraint at the specified index from the /// collection. ////// public void Remove(string name) { Constraint c = this[name]; if (c == null) throw ExceptionBuilder.ConstraintNotInTheTable(name); Remove(c); } ///Removes the constraint, specified by name, from the collection. ////// Unregisters this name as no longer being used in the collection. Called by Remove, All property, and /// Constraint.ConstraintName property. If the name is equivalent to the last proposed default namem, we walk backwards /// to find the next proper default name to hang out. /// internal void UnregisterName(string name) { if (NamesEqual(name, MakeName(defaultNameIndex - 1), true, table.Locale) != 0) { do { defaultNameIndex--; } while (defaultNameIndex > 1 && !Contains(MakeName(defaultNameIndex - 1))); } } internal void FinishInitConstraints() { if (delayLoadingConstraints == null) return; int colCount; DataColumn[] parents, childs; for (int i = 0; i < delayLoadingConstraints.Length; i++) { if (delayLoadingConstraints[i] is UniqueConstraint) { if (fLoadForeignKeyConstraintsOnly) continue; UniqueConstraint constr = (UniqueConstraint) delayLoadingConstraints[i]; if (constr.columnNames == null) { this.Add(constr); continue; } colCount = constr.columnNames.Length; parents = new DataColumn[colCount]; for (int j = 0; j < colCount; j++) parents[j] = table.Columns[constr.columnNames[j]]; if (constr.bPrimaryKey) { if (table.primaryKey != null) { throw ExceptionBuilder.AddPrimaryKeyConstraint(); } else { Add(constr.ConstraintName,parents,true); } continue; } UniqueConstraint newConstraint = new UniqueConstraint(constr.constraintName, parents); if (FindConstraint(newConstraint) == null) this.Add(newConstraint); } else { ForeignKeyConstraint constr = (ForeignKeyConstraint) delayLoadingConstraints[i]; if (constr.parentColumnNames == null ||constr.childColumnNames == null) { this.Add(constr); continue; } if (table.DataSet == null) { fLoadForeignKeyConstraintsOnly = true; continue; } colCount = constr.parentColumnNames.Length; parents = new DataColumn[colCount]; childs = new DataColumn[colCount]; for (int j = 0; j < colCount; j++) { if (constr.parentTableNamespace == null) parents[j] = table.DataSet.Tables[constr.parentTableName].Columns[constr.parentColumnNames[j]]; else parents[j] = table.DataSet.Tables[constr.parentTableName, constr.parentTableNamespace].Columns[constr.parentColumnNames[j]]; childs[j] = table.Columns[constr.childColumnNames[j]]; } ForeignKeyConstraint newConstraint = new ForeignKeyConstraint(constr.constraintName, parents, childs); newConstraint.AcceptRejectRule = constr.acceptRejectRule; newConstraint.DeleteRule = constr.deleteRule; newConstraint.UpdateRule = constr.updateRule; this.Add(newConstraint); } } if (!fLoadForeignKeyConstraintsOnly) delayLoadingConstraints = null; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //[....] //[....] //----------------------------------------------------------------------------- namespace System.Data { using System; using System.Diagnostics; using System.Collections; using System.ComponentModel; ////// [ DefaultEvent("CollectionChanged"), Editor("Microsoft.VSDesigner.Data.Design.ConstraintsCollectionEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing), ] #if WINFSInternalOnly internal #else public #endif sealed class ConstraintCollection : InternalDataCollectionBase { // WebData 111752 private readonly DataTable table; // private Constraint[] constraints = new Constraint[2]; private readonly ArrayList list = new ArrayList(); private int defaultNameIndex = 1; private CollectionChangeEventHandler onCollectionChanged; private Constraint[] delayLoadingConstraints; private bool fLoadForeignKeyConstraintsOnly = false; ///Represents a collection of constraints for a ////// . /// ConstraintCollection constructor. Used only by DataTable. /// internal ConstraintCollection(DataTable table) { this.table = table; } ////// protected override ArrayList List { get { return list; } } ///Gets the list of objects contained by the collection. ////// public Constraint this[int index] { get { if (index >= 0 && index < List.Count) { return(Constraint) List[index]; } throw ExceptionBuilder.ConstraintOutOfRange(index); } } ///Gets the ////// from the collection at the specified index. /// The DataTable with which this ConstraintCollection is associated /// internal DataTable Table { get { return table; } } ////// public Constraint this[string name] { get { int index = InternalIndexOf(name); if (index == -2) { throw ExceptionBuilder.CaseInsensitiveNameConflict(name); } return (index < 0) ? null : (Constraint)List[index]; } } ///Gets the ///from the collection with the specified name. /// public void Add(Constraint constraint) { Add(constraint, true); } // To add foreign key constraint without adding any unique constraint for internal use. Main purpose : Binary Remoting internal void Add(Constraint constraint, bool addUniqueWhenAddingForeign) { if (constraint == null) throw ExceptionBuilder.ArgumentNull("constraint"); // It is an error if we find an equivalent constraint already in collection if (FindConstraint(constraint) != null) { throw ExceptionBuilder.DuplicateConstraint(FindConstraint(constraint).ConstraintName); } if (1 < table.NestedParentRelations.Length) { if (!AutoGenerated(constraint)) { throw ExceptionBuilder.CantAddConstraintToMultipleNestedTable(table.TableName); } } if (constraint is UniqueConstraint) { if (((UniqueConstraint)constraint).bPrimaryKey) { if (Table.primaryKey != null) { throw ExceptionBuilder.AddPrimaryKeyConstraint(); } } AddUniqueConstraint((UniqueConstraint)constraint); } else if (constraint is ForeignKeyConstraint) { ForeignKeyConstraint fk = (ForeignKeyConstraint)constraint; if (addUniqueWhenAddingForeign) { UniqueConstraint key = fk.RelatedTable.Constraints.FindKeyConstraint(fk.RelatedColumnsReference); if (key == null) { if (constraint.ConstraintName.Length == 0) constraint.ConstraintName = AssignName(); else RegisterName(constraint.ConstraintName); key = new UniqueConstraint(fk.RelatedColumnsReference); fk.RelatedTable.Constraints.Add(key); } } AddForeignKeyConstraint((ForeignKeyConstraint)constraint); } BaseAdd(constraint); ArrayAdd(constraint); OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Add, constraint)); if (constraint is UniqueConstraint) { if (((UniqueConstraint)constraint).bPrimaryKey) { Table.PrimaryKey = ((UniqueConstraint)constraint).ColumnsReference; } } } ////// Adds the constraint to the collection. ////// public Constraint Add(string name, DataColumn[] columns, bool primaryKey) { UniqueConstraint constraint = new UniqueConstraint(name, columns); Add(constraint); if (primaryKey) Table.PrimaryKey = columns; return constraint; } ///Constructs a new ///using the /// specified array of /// objects and adds it to the collection. /// public Constraint Add(string name, DataColumn column, bool primaryKey) { UniqueConstraint constraint = new UniqueConstraint(name, column); Add(constraint); if (primaryKey) Table.PrimaryKey = constraint.ColumnsReference; return constraint; } ///Constructs a new ///using the /// specified and adds it to the collection. /// public Constraint Add(string name, DataColumn primaryKeyColumn, DataColumn foreignKeyColumn) { ForeignKeyConstraint constraint = new ForeignKeyConstraint(name, primaryKeyColumn, foreignKeyColumn); Add(constraint); return constraint; } ////// Constructs a new ////// with the /// specified parent and child /// columns and adds the constraint to the collection. /// public Constraint Add(string name, DataColumn[] primaryKeyColumns, DataColumn[] foreignKeyColumns) { ForeignKeyConstraint constraint = new ForeignKeyConstraint(name, primaryKeyColumns, foreignKeyColumns); Add(constraint); return constraint; } public void AddRange(Constraint[] constraints ) { if (table.fInitInProgress) { delayLoadingConstraints = constraints; fLoadForeignKeyConstraintsOnly = false; return; } if (constraints != null) { foreach(Constraint constr in constraints) { if (constr != null) { Add(constr); } } } } private void AddUniqueConstraint(UniqueConstraint constraint) { DataColumn[] columns = constraint.ColumnsReference; for (int i = 0; i < columns.Length; i++) { if (columns[i].Table != this.table) { throw ExceptionBuilder.ConstraintForeignTable(); } } constraint.ConstraintIndexInitialize(); if (!constraint.CanEnableConstraint()) { constraint.ConstraintIndexClear(); throw ExceptionBuilder.UniqueConstraintViolation(); } } private void AddForeignKeyConstraint(ForeignKeyConstraint constraint) { if (!constraint.CanEnableConstraint()) { throw ExceptionBuilder.ConstraintParentValues(); } constraint.CheckCanAddToCollection(this); } private bool AutoGenerated(Constraint constraint) { ForeignKeyConstraint fk = (constraint as ForeignKeyConstraint); if (null != fk) { return XmlTreeGen.AutoGenerated(fk, false); } else { UniqueConstraint unique = (UniqueConstraint) constraint; return XmlTreeGen.AutoGenerated(unique); } } ///Constructs a new ///with the specified parent columns and /// child columns and adds the constraint to the collection. /// public event CollectionChangeEventHandler CollectionChanged { add { onCollectionChanged += value; } remove { onCollectionChanged -= value; } } ///Occurs when the ///is changed through additions or /// removals. /// Adds the constraint to the constraints array. /// private void ArrayAdd(Constraint constraint) { Debug.Assert(constraint != null, "Attempt to add null constraint to constraint array"); List.Add(constraint); } private void ArrayRemove(Constraint constraint) { List.Remove(constraint); } ////// Creates a new default name. /// internal string AssignName() { string newName = MakeName(defaultNameIndex); defaultNameIndex++; return newName; } ////// Does verification on the constraint and it's name. /// An ArgumentNullException is thrown if this constraint is null. An ArgumentException is thrown if this constraint /// already belongs to this collection, belongs to another collection. /// A DuplicateNameException is thrown if this collection already has a constraint with the same /// name (case insensitive). /// private void BaseAdd(Constraint constraint) { if (constraint == null) throw ExceptionBuilder.ArgumentNull("constraint"); if (constraint.ConstraintName.Length == 0) constraint.ConstraintName = AssignName(); else RegisterName(constraint.ConstraintName); constraint.InCollection = true; } ////// BaseGroupSwitch will intelligently remove and add tables from the collection. /// private void BaseGroupSwitch(Constraint[] oldArray, int oldLength, Constraint[] newArray, int newLength) { // We're doing a smart diff of oldArray and newArray to find out what // should be removed. We'll pass through oldArray and see if it exists // in newArray, and if not, do remove work. newBase is an opt. in case // the arrays have similar prefixes. int newBase = 0; for (int oldCur = 0; oldCur < oldLength; oldCur++) { bool found = false; for (int newCur = newBase; newCur < newLength; newCur++) { if (oldArray[oldCur] == newArray[newCur]) { if (newBase == newCur) { newBase++; } found = true; break; } } if (!found) { // This means it's in oldArray and not newArray. Remove it. BaseRemove(oldArray[oldCur]); List.Remove(oldArray[oldCur]); } } // Now, let's pass through news and those that don't belong, add them. for (int newCur = 0; newCur < newLength; newCur++) { if (!newArray[newCur].InCollection) BaseAdd(newArray[newCur]); List.Add(newArray[newCur]); } } ////// Does verification on the constraint and it's name. /// An ArgumentNullException is thrown if this constraint is null. An ArgumentException is thrown /// if this constraint doesn't belong to this collection or if this constraint is part of a relationship. /// private void BaseRemove(Constraint constraint) { if (constraint == null) { throw ExceptionBuilder.ArgumentNull("constraint"); } if (constraint.Table != table) { throw ExceptionBuilder.ConstraintRemoveFailed(); } UnregisterName(constraint.ConstraintName); constraint.InCollection = false; if (constraint is UniqueConstraint) { for (int i = 0; i < Table.ChildRelations.Count; i++) { DataRelation rel = Table.ChildRelations[i]; if (rel.ParentKeyConstraint == constraint) rel.SetParentKeyConstraint(null); } ((UniqueConstraint)constraint).ConstraintIndexClear(); } else if (constraint is ForeignKeyConstraint) { for (int i = 0; i < Table.ParentRelations.Count; i++) { DataRelation rel = Table.ParentRelations[i]; if (rel.ChildKeyConstraint == constraint) rel.SetChildKeyConstraint(null); } } } ////// // PUBLIC because called by design-time... need to consider this. public bool CanRemove(Constraint constraint) { return CanRemove(constraint, /*fThrowException:*/false); } internal bool CanRemove(Constraint constraint, bool fThrowException) { return constraint.CanBeRemovedFromCollection(this, fThrowException); } ///Indicates if a ///can be removed. /// public void Clear() { if (table != null) { table.PrimaryKey = null; for (int i = 0; i < table.ParentRelations.Count; i++) { table.ParentRelations[i].SetChildKeyConstraint(null); } for (int i = 0; i < table.ChildRelations.Count; i++) { table.ChildRelations[i].SetParentKeyConstraint(null); } } if (table.fInitInProgress && delayLoadingConstraints != null) { delayLoadingConstraints = null; fLoadForeignKeyConstraintsOnly = false; } int oldLength = List.Count; Constraint[] constraints = new Constraint[List.Count]; List.CopyTo(constraints, 0); try { // this will smartly add and remove the appropriate tables. BaseGroupSwitch(constraints, oldLength, null, 0); } catch (Exception e) { // if (Common.ADP.IsCatchableOrSecurityExceptionType(e)) { // something messed up. restore to original state. BaseGroupSwitch(null, 0, constraints, oldLength); List.Clear(); for (int i = 0; i < oldLength; i++) List.Add(constraints[i]); } throw; } List.Clear(); OnCollectionChanged(RefreshEventArgs); } ///Clears the collection of any ////// objects. /// public bool Contains(string name) { return (InternalIndexOf(name) >= 0); } internal bool Contains(string name, bool caseSensitive) { if (!caseSensitive) return Contains(name); int index = InternalIndexOf(name); if (index<0) return false; return (name == ((Constraint) List[index]).ConstraintName); } public void CopyTo(Constraint[] array, int index) { if (array==null) throw ExceptionBuilder.ArgumentNull("array"); if (index < 0) throw ExceptionBuilder.ArgumentOutOfRange("index"); if (array.Length - index < list.Count) throw ExceptionBuilder.InvalidOffsetLength(); for(int i = 0; i < list.Count; ++i) { array[index + i] = (Constraint)list[i]; } } ///Indicates whether the ///, specified by name, exists in the collection. /// Returns a matching constriant object. /// internal Constraint FindConstraint(Constraint constraint) { int constraintCount = List.Count; for (int i = 0; i < constraintCount; i++) { if (((Constraint)List[i]).Equals(constraint)) return(Constraint)List[i]; } return null; } ////// Returns a matching constriant object. /// internal UniqueConstraint FindKeyConstraint(DataColumn[] columns) { int constraintCount = List.Count; for (int i = 0; i < constraintCount; i++) { UniqueConstraint constraint = (List[i] as UniqueConstraint); if ((null != constraint) && CompareArrays(constraint.Key.ColumnsReference, columns)) { return constraint; } } return null; } ////// Returns a matching constriant object. /// internal UniqueConstraint FindKeyConstraint(DataColumn column) { int constraintCount = List.Count; for (int i = 0; i < constraintCount; i++) { UniqueConstraint constraint = (List[i] as UniqueConstraint); if ((null != constraint) && (constraint.Key.ColumnsReference.Length == 1) && (constraint.Key.ColumnsReference[0] == column)) return constraint; } return null; } ////// Returns a matching constriant object. /// internal ForeignKeyConstraint FindForeignKeyConstraint(DataColumn[] parentColumns, DataColumn[] childColumns) { int constraintCount = List.Count; for (int i = 0; i < constraintCount; i++) { ForeignKeyConstraint constraint = (List[i] as ForeignKeyConstraint); if ((null != constraint) && CompareArrays(constraint.ParentKey.ColumnsReference, parentColumns) && CompareArrays(constraint.ChildKey.ColumnsReference, childColumns)) return constraint; } return null; } private static bool CompareArrays(DataColumn[] a1, DataColumn[] a2) { Debug.Assert(a1 != null && a2 != null, "Invalid Arguments"); if (a1.Length != a2.Length) return false; int i, j; for (i=0; i/// Returns the index of the specified /// public int IndexOf(Constraint constraint) { if (null != constraint) { int count = Count; for (int i = 0; i < count; ++i) { if (constraint == (Constraint) List[i]) return i; } // didnt find the constraint } return -1; } ///. /// public int IndexOf(string constraintName) { int index = InternalIndexOf(constraintName); return (index < 0) ? -1 : index; } // Return value: // >= 0: find the match // -1: No match // -2: At least two matches with different cases internal int InternalIndexOf(string constraintName) { int cachedI = -1; if ((null != constraintName) && (0 < constraintName.Length)) { int constraintCount = List.Count; int result = 0; for (int i = 0; i < constraintCount; i++) { Constraint constraint = (Constraint) List[i]; result = NamesEqual(constraint.ConstraintName, constraintName, false, table.Locale); if (result == 1) return i; if (result == -1) cachedI = (cachedI == -1) ? i : -2; } } return cachedI; } ///Returns the index of the ///, specified by name. /// Makes a default name with the given index. e.g. Constraint1, Constraint2, ... Constrainti /// private string MakeName(int index) { if (1 == index) { return "Constraint1"; } return "Constraint" + index.ToString(System.Globalization.CultureInfo.InvariantCulture); } ////// private void OnCollectionChanged(CollectionChangeEventArgs ccevent) { if (onCollectionChanged != null) { onCollectionChanged(this, ccevent); } } ///Raises the ///event. /// Registers this name as being used in the collection. Will throw an ArgumentException /// if the name is already being used. Called by Add, All property, and Constraint.ConstraintName property. /// if the name is equivalent to the next default name to hand out, we increment our defaultNameIndex. /// internal void RegisterName(string name) { Debug.Assert (name != null); int constraintCount = List.Count; for (int i = 0; i < constraintCount; i++) { if (NamesEqual(name, ((Constraint)List[i]).ConstraintName, true, table.Locale) != 0) { throw ExceptionBuilder.DuplicateConstraintName(((Constraint)List[i]).ConstraintName); } } if (NamesEqual(name, MakeName(defaultNameIndex), true, table.Locale) != 0) { defaultNameIndex++; } } ////// public void Remove(Constraint constraint) { if (constraint == null) throw ExceptionBuilder.ArgumentNull("constraint"); // this will throw an exception if it can't be removed, otherwise indicates // whether we need to remove it from the collection. if (CanRemove(constraint, true)) { // constraint can be removed BaseRemove(constraint); ArrayRemove(constraint); if (constraint is UniqueConstraint && ((UniqueConstraint)constraint).IsPrimaryKey) { Table.PrimaryKey = null; } OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Remove, constraint)); } } ////// Removes the specified ////// from the collection. /// public void RemoveAt(int index) { Constraint c = this[index]; if (c == null) throw ExceptionBuilder.ConstraintOutOfRange(index); Remove(c); } ///Removes the constraint at the specified index from the /// collection. ////// public void Remove(string name) { Constraint c = this[name]; if (c == null) throw ExceptionBuilder.ConstraintNotInTheTable(name); Remove(c); } ///Removes the constraint, specified by name, from the collection. ////// Unregisters this name as no longer being used in the collection. Called by Remove, All property, and /// Constraint.ConstraintName property. If the name is equivalent to the last proposed default namem, we walk backwards /// to find the next proper default name to hang out. /// internal void UnregisterName(string name) { if (NamesEqual(name, MakeName(defaultNameIndex - 1), true, table.Locale) != 0) { do { defaultNameIndex--; } while (defaultNameIndex > 1 && !Contains(MakeName(defaultNameIndex - 1))); } } internal void FinishInitConstraints() { if (delayLoadingConstraints == null) return; int colCount; DataColumn[] parents, childs; for (int i = 0; i < delayLoadingConstraints.Length; i++) { if (delayLoadingConstraints[i] is UniqueConstraint) { if (fLoadForeignKeyConstraintsOnly) continue; UniqueConstraint constr = (UniqueConstraint) delayLoadingConstraints[i]; if (constr.columnNames == null) { this.Add(constr); continue; } colCount = constr.columnNames.Length; parents = new DataColumn[colCount]; for (int j = 0; j < colCount; j++) parents[j] = table.Columns[constr.columnNames[j]]; if (constr.bPrimaryKey) { if (table.primaryKey != null) { throw ExceptionBuilder.AddPrimaryKeyConstraint(); } else { Add(constr.ConstraintName,parents,true); } continue; } UniqueConstraint newConstraint = new UniqueConstraint(constr.constraintName, parents); if (FindConstraint(newConstraint) == null) this.Add(newConstraint); } else { ForeignKeyConstraint constr = (ForeignKeyConstraint) delayLoadingConstraints[i]; if (constr.parentColumnNames == null ||constr.childColumnNames == null) { this.Add(constr); continue; } if (table.DataSet == null) { fLoadForeignKeyConstraintsOnly = true; continue; } colCount = constr.parentColumnNames.Length; parents = new DataColumn[colCount]; childs = new DataColumn[colCount]; for (int j = 0; j < colCount; j++) { if (constr.parentTableNamespace == null) parents[j] = table.DataSet.Tables[constr.parentTableName].Columns[constr.parentColumnNames[j]]; else parents[j] = table.DataSet.Tables[constr.parentTableName, constr.parentTableNamespace].Columns[constr.parentColumnNames[j]]; childs[j] = table.Columns[constr.childColumnNames[j]]; } ForeignKeyConstraint newConstraint = new ForeignKeyConstraint(constr.constraintName, parents, childs); newConstraint.AcceptRejectRule = constr.acceptRejectRule; newConstraint.DeleteRule = constr.deleteRule; newConstraint.UpdateRule = constr.updateRule; this.Add(newConstraint); } } if (!fLoadForeignKeyConstraintsOnly) delayLoadingConstraints = null; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- RequestNavigateEventArgs.cs
- ContainerVisual.cs
- MetadataCache.cs
- securitymgrsite.cs
- Bezier.cs
- Bits.cs
- nulltextnavigator.cs
- ListViewItem.cs
- PrePostDescendentsWalker.cs
- CompositeScriptReferenceEventArgs.cs
- LabelLiteral.cs
- InkCanvas.cs
- TreeViewItem.cs
- SkipStoryboardToFill.cs
- LicenseManager.cs
- VirtualDirectoryMappingCollection.cs
- ListParaClient.cs
- HotSpotCollection.cs
- TableLayoutStyle.cs
- HostedTransportConfigurationBase.cs
- SQLByteStorage.cs
- RegisteredScript.cs
- CommonObjectSecurity.cs
- SerializerProvider.cs
- WorkflowInstanceProvider.cs
- EncryptedPackage.cs
- SchemaNames.cs
- SiteOfOriginPart.cs
- StringFunctions.cs
- Encoder.cs
- ActivityExecutorDelegateInfo.cs
- LinearKeyFrames.cs
- ApplicationFileCodeDomTreeGenerator.cs
- SortedList.cs
- TrackBarRenderer.cs
- HideDisabledControlAdapter.cs
- TransactionChannelFactory.cs
- HttpGetProtocolImporter.cs
- CustomAttributeFormatException.cs
- DetailsViewUpdatedEventArgs.cs
- SiteIdentityPermission.cs
- ObjectHelper.cs
- Pkcs7Signer.cs
- COM2Enum.cs
- Fx.cs
- ObjectDataSourceStatusEventArgs.cs
- DataBoundLiteralControl.cs
- CodeGroup.cs
- SchemaTypeEmitter.cs
- MembershipUser.cs
- CalendarDay.cs
- SubclassTypeValidatorAttribute.cs
- Point4DConverter.cs
- WebPartCatalogCloseVerb.cs
- TabPageDesigner.cs
- XmlSchemaDatatype.cs
- CalendarAutoFormat.cs
- ClientSection.cs
- XmlSchemaAll.cs
- XamlTypeMapper.cs
- Matrix3DConverter.cs
- SspiNegotiationTokenProviderState.cs
- RemotingConfigParser.cs
- SafePointer.cs
- DesignerRegion.cs
- CollectionChangeEventArgs.cs
- TextRangeBase.cs
- HttpApplicationFactory.cs
- ColumnReorderedEventArgs.cs
- ApplicationContext.cs
- BaseProcessor.cs
- WebControlParameterProxy.cs
- DataGridViewRowCancelEventArgs.cs
- Italic.cs
- Timeline.cs
- safesecurityhelperavalon.cs
- TemplateLookupAction.cs
- GiveFeedbackEvent.cs
- DescendentsWalker.cs
- OrCondition.cs
- LineBreak.cs
- EntityChangedParams.cs
- IRCollection.cs
- AssemblyAttributes.cs
- OuterProxyWrapper.cs
- PersistChildrenAttribute.cs
- PageTheme.cs
- TimeIntervalCollection.cs
- MediaEntryAttribute.cs
- CompositeFontInfo.cs
- BrowserTree.cs
- WebPartAuthorizationEventArgs.cs
- DynamicControlParameter.cs
- GridViewRowEventArgs.cs
- KeyProperty.cs
- FixedPageProcessor.cs
- DataSourceControlBuilder.cs
- EntitySetBase.cs
- ResourceReferenceExpression.cs
- _UncName.cs