2 // System.Data.Constraint.cs
5 // Franklin Wise <gracenote@earthlink.net>
7 // Tim Coleman (tim@timcoleman.com)
10 // (C) Ximian, Inc. 2002
11 // Copyright (C) Tim Coleman, 2002
15 using System.Collections;
16 using System.ComponentModel;
17 using System.Runtime.InteropServices;
18 using System.Runtime.Serialization;
20 namespace System.Data {
22 internal delegate void DelegateConstraintNameChange (object sender, string newName);
24 [DefaultProperty ("ConstraintName")]
26 [TypeConverterAttribute (typeof (ConstraintConverter))]
27 public abstract class Constraint
29 internal event DelegateConstraintNameChange BeforeConstraintNameChange;
31 //if constraintName is not set then a name is
32 //created when it is added to
33 //the ConstraintCollection
34 //it can not be set to null, empty or duplicate
35 //once it has been added to the collection
36 private string _constraintName;
37 private PropertyCollection _properties;
41 //Used for membership checking
42 private ConstraintCollection _constraintCollection;
46 protected Constraint ()
49 _properties = new PropertyCollection();
52 protected internal virtual DataSet _DataSet {
53 get { return dataSet; }
56 [DataCategory ("Data")]
57 [DataSysDescription ("Indicates the name of this constraint.")]
59 public virtual string ConstraintName {
60 get{ return "" + _constraintName; }
62 //This should only throw an exception when it
63 //is a member of a ConstraintCollection which
64 //means we should let the ConstraintCollection
65 //handle exceptions when this value changes
66 _onConstraintNameChange(value);
67 _constraintName = value;
72 [DataCategory ("Data")]
73 [DataSysDescription ("The collection that holds custom user information.")]
74 public PropertyCollection ExtendedProperties {
75 get { return _properties; }
78 [DataSysDescription ("Indicates the table of this constraint.")]
79 public abstract DataTable Table {
83 internal ConstraintCollection ConstraintCollection {
84 get{ return _constraintCollection; }
85 set{ _constraintCollection = value; }
88 private void _onConstraintNameChange (string newName)
90 if (null != BeforeConstraintNameChange)
92 BeforeConstraintNameChange (this, newName);
96 //call once before adding a constraint to a collection
97 //will throw an exception to prevent the add if a rule is broken
98 internal virtual void AddToConstraintCollectionSetup (ConstraintCollection collection)
102 internal virtual void AssertConstraint ()
106 internal virtual void AssertConstraint (DataRow row)
110 internal virtual void RollbackAssert (DataRow row)
114 //call once before removing a constraint to a collection
115 //can throw an exception to prevent the removal
116 internal virtual void RemoveFromConstraintCollectionCleanup (ConstraintCollection collection)
121 protected void CheckStateForProperty ()
123 throw new NotImplementedException ();
126 protected internal void SetDataSet (DataSet dataSet)
128 this.dataSet = dataSet;
141 protected internal void UpdateIndex (DataRow row)
143 if (row.RowState == DataRowState.Detached || row.RowState == DataRowState.Unchanged)
144 Index.Insert (new Node (row), DataRowVersion.Default);
145 else if ((row.RowState == DataRowState.Modified) || (row.RowState == DataRowState.Added)) {
146 // first we check if the values of the key changed.
147 bool keyChanged = false;
148 for (int i = 0; i < Index.Columns.Length; i++) {
149 if (row[Index.Columns[i], DataRowVersion.Default] != row[Index.Columns[i], DataRowVersion.Current]) {
153 // if key changed we first try to insert a new node
154 // and,if succeded, we delete the row's old node.
157 // insert new node for the row
158 // note : may throw if not succeded
159 Index.Insert (new Node (row), DataRowVersion.Default);
161 // delete the row's node
167 protected internal void RollbackIndex (DataRow row)
169 Node n = Index.Find(row, DataRowVersion.Default);
171 throw new ConstraintException("Row was not found in constraint index");
173 // first remove the node inserted as a result of last AssertConstraint on the row
176 // if the row is not detached we should add back to the index
177 // node corresponding to row value before AssertConstraint was called
178 if(row.RowState != DataRowState.Detached){
179 // since index before we updated index was ok, insert should always suceed
180 // maybe we still need to try/catch here
181 Index.Insert(new Node(row), DataRowVersion.Current);
187 /// Gets the ConstraintName, if there is one, as a string.
189 public override string ToString ()
191 return "" + _constraintName;