+2002-08-15 Franklin Wise <gracenote@earthlink.net>
+
+ * System.Data/Constraint.cs: Added helper virtual functions
+
+ * System.Data/ConstraintCollection.cs: Improved constraint removal,
+ validation. Removed specific knowledge of subclasses of
+ Constraint.
+
+ * System.Data/DataColumn.cs: Added static helper function to compare
+ if two DataColumn arrays are the same.
+
+ * System.Data/ForeignKeyConstraint.cs: Continued to flush out.
+
+ * System.Data/UniqueConstraint.cs: Implemented. Still some constraint
+ validation to do.
+
2002-08-13 Franklin Wise <gracenote@earthlink.net>
* System.Data/DataRow.cs: Added several fixme tags.
internal event DelegateConstraintNameChange
BeforeConstraintNameChange;
- private string _name = null;
+ //if constraintName is not set then a name is
+ //created when it is added to
+ //the ConstraintCollection
+ //it can not be set to null, empty or duplicate
+ //once it has been added to the collection
+ private string _constraintName = null;
private PropertyCollection _properties = null;
//Used for membership checking
public virtual string ConstraintName {
get{
- return "" + _name;
+ return "" + _constraintName;
}
set{
//means we should let the ConstraintCollection
//handle exceptions when this value changes
_onConstraintNameChange(value);
- _name = value;
+ _constraintName = value;
}
}
/// </summary>
public override string ToString()
{
- return "" + _name;
+ return "" + _constraintName;
}
internal ConstraintCollection ConstraintCollection {
}
-
private void _onConstraintNameChange(string newName)
{
if (null != BeforeConstraintNameChange)
}
}
+ //call once before adding a constraint to a collection
+ //will throw an exception to prevent the add if a rule is broken
+ internal protected abstract void AddToConstraintCollectionSetup(
+ ConstraintCollection collection);
+
+ //call once before removing a constraint to a collection
+ //can throw an exception to prevent the removal
+ internal protected abstract void RemoveFromConstraintCollectionCleanup(
+ ConstraintCollection collection);
+
+
+ //Call to Validate the constraint
+ //Will throw if constraint is violated
+ internal abstract void AssertConstraint();
+
}
}
{
[Serializable]
internal delegate void DelegateValidateRemoveConstraint(ConstraintCollection sender,
- Constraint constraintToRemove, ref bool cancel);
+ Constraint constraintToRemove, ref bool fail,ref string failReason);
/// <summary>
/// hold collection of constraints for data table
public virtual Constraint this[string name] {
get {
- int index = IndexOf(name);
+ //If the name is not found we just return null
+ int index = IndexOf(name); //case insensitive
if (-1 == index) return null;
return this[index];
}
public virtual Constraint this[int index] {
get {
+ if (index < 0 || index >= List.Count)
+ throw new IndexOutOfRangeException();
return (Constraint)List[index];
}
}
if (null != constraint.ConstraintCollection)
throw new ArgumentException("Constraint already belongs to another collection.");
- //check for duplicate
+ //check for duplicate name
if (_isDuplicateConstraintName(constraint.ConstraintName,null) )
throw new DuplicateNameException("Constraint name already exists.");
+ //Allow constraint to run validation rules and setup
+ constraint.AddToConstraintCollectionSetup(this); //may throw if it can't setup
+
+ //Run Constraint to check existing data in table
+ constraint.AssertConstraint();
+
//if name is null or empty give it a name
if (constraint.ConstraintName == null ||
constraint.ConstraintName == "" )
//spec says nothing about this
if (null == constraint) throw new ArgumentNullException("Constraint can't be null.");
- //if we are not a unique constraint then it's ok to remove
- UniqueConstraint uc = constraint as UniqueConstraint;
- if (null == uc) return true;
-
//LAMESPEC: spec says return false (which makes sense) and throw exception for False case (?).
+ //TODO: I may want to change how this is done
+ //maybe put a CanRemove on the Constraint class
+ //and have the Constraint fire this event
+
//discover if there is a related ForeignKey
- return _canRemoveConstraint(constraint);
+ string failReason ="";
+ return _canRemoveConstraint(constraint, ref failReason);
}
//not null
if (null == constraint) throw new ArgumentNullException();
+ string failReason = "";
+ if (! _canRemoveConstraint(constraint, ref failReason) )
+ {
+ if (failReason != null || failReason != "")
+ throw new ArgumentException(failReason);
+ else
+ throw new ArgumentException("Can't remove constraint.");
+ }
+
+ constraint.RemoveFromConstraintCollectionCleanup(this);
List.Remove(constraint);
OnCollectionChanged( new CollectionChangeEventArgs(CollectionChangeAction.Remove,this));
}
throw new IndexOutOfRangeException("Index out of range, index = "
+ index.ToString() + ".");
+ this[index].RemoveFromConstraintCollectionCleanup(this);
List.RemoveAt(index);
OnCollectionChanged( new CollectionChangeEventArgs(CollectionChangeAction.Remove,this));
}
}
}
- private bool _canRemoveConstraint(Constraint constraint )
+ private bool _canRemoveConstraint(Constraint constraint, ref string failReason )
{
bool cancel = false;
+ string tmp = "";
if (null != ValidateRemoveConstraint)
{
- ValidateRemoveConstraint(this, constraint, ref cancel);
+ ValidateRemoveConstraint(this, constraint, ref cancel, ref tmp);
}
+ failReason = tmp;
return !cancel;
}
}
namespace System.Data
{
+ internal delegate void DelegateColumnValueChange(DataColumn column,
+ DataRow row, object proposedValue);
+
+
/// <summary>
/// Summary description for DataColumn.
/// </summary>
public class DataColumn : MarshalByValueComponent
{
+ #region Events
+ [MonoTODO]
+ //used for constraint validation
+ //if an exception is fired during this event the change should be canceled
+ internal event DelegateColumnValueChange ValidateColumnValueChange;
+
+ //used for FK Constraint Cascading rules
+ internal event DelegateColumnValueChange ColumnValueChanging;
+ #endregion //Events
+
+
#region Fields
private bool allowDBNull = true;
// and DataColumnCollection
}
+
+ // Returns true if all the same collumns are in columnSet and compareSet
+ internal static bool AreColumnSetsTheSame(DataColumn[] columnSet, DataColumn[] compareSet)
+ {
+ if (null == columnSet && null == compareSet) return true;
+ if (null == columnSet || null == compareSet) return false;
+
+ if (columnSet.Length != compareSet.Length) return false;
+
+ foreach (DataColumn col in columnSet)
+ {
+ bool matchFound = false;
+ foreach (DataColumn compare in compareSet)
+ {
+ if (col == compare)
+ {
+ matchFound = true;
+ }
+ }
+ if (! matchFound) return false;
+ }
+
+ return true;
+ }
+
#endregion // Methods
}
namespace System.Data
{
- [Serializable]\r
+ [Serializable]
public class ForeignKeyConstraint : Constraint {
+ private UniqueConstraint _parentUniqueConstraint;
+ private DataColumn [] _parentColumns;
+ private DataColumn [] _childColumns;
+ private Rule _deleteRule;
+ private Rule _updateRule;
+ private AcceptRejectRule _acceptRejectRule;
+
#region Constructors
- [MonoTODO]\r
- public ForeignKeyConstraint(DataColumn parentColumn, \r
- DataColumn childColumn) {
- }
+ public ForeignKeyConstraint(DataColumn parentColumn, DataColumn childColumn)
+ {
+ if (null == parentColumn || null == childColumn) {
+ throw new ArgumentNullException("Neither parentColumn or" +
+ " childColumn can be null.");
+ }
- [MonoTODO]\r
- public ForeignKeyConstraint(DataColumn[] parentColumns,\r
- DataColumn[] childColumns) {
+ _foreignKeyConstraint(null, new DataColumn[] {parentColumn},
+ new DataColumn[] {childColumn});
}
- [MonoTODO]\r
- public ForeignKeyConstraint(string constraintName,\r
- DataColumn parentColumn, DataColumn childColumn) {
+ public ForeignKeyConstraint(DataColumn[] parentColumns, DataColumn[] childColumns)
+ {
+ _foreignKeyConstraint(null, parentColumns, childColumns);
}
- [MonoTODO]\r
- public ForeignKeyConstraint(string constraintName,\r
- DataColumn[] parentColumns, \r
- DataColumn[] childColumns) {
+ public ForeignKeyConstraint(string constraintName,
+ DataColumn parentColumn, DataColumn childColumn)
+ {
+ if (null == parentColumn || null == childColumn) {
+ throw new ArgumentNullException("Neither parentColumn or" +
+ " childColumn can be null.");
+ }
+
+ _foreignKeyConstraint(constraintName, new DataColumn[] {parentColumn},
+ new DataColumn[] {childColumn});
}
- [MonoTODO]\r
- public ForeignKeyConstraint(string constraintName,\r
- string parentTableName, string[] parentColumnNames,\r
- string[] childColumnNames, \r
- AcceptRejectRule acceptRejectRule, Rule deleteRule,\r
+ public ForeignKeyConstraint(string constraintName,
+ DataColumn[] parentColumns, DataColumn[] childColumns)
+ {
+ _foreignKeyConstraint(constraintName, parentColumns, childColumns);
+ }
+
+ //special case
+ [MonoTODO]
+ public ForeignKeyConstraint(string constraintName,
+ string parentTableName, string[] parentColumnNames,
+ string[] childColumnNames,
+ AcceptRejectRule acceptRejectRule, Rule deleteRule,
Rule updateRule) {
}
+
+ private void _foreignKeyConstraint(string constraintName, DataColumn[] parentColumns,
+ DataColumn[] childColumns)
+ {
+
+ //Validate
+ _validateCtor(parentColumns, childColumns);
+
+ //Set Constraint Name
+ base.ConstraintName = constraintName;
+
+ //Keep reference to columns
+ _parentColumns = parentColumns;
+ _childColumns = childColumns;
+ }
+
+ [MonoTODO]
+ private void _validateCtor(DataColumn[] parentColumns, DataColumn[] childColumns)
+ {
+ //not null
+ if (null == parentColumns || null == childColumns)
+ throw new ArgumentNullException();
+
+ if (parentColumns.Length < 1 || childColumns.Length < 1)
+ throw new ArgumentException("Neither ParentColumns or ChildColumns can't be" +
+ " zero length.");
+
+ //DataTypes must match
+ //column sets must all be from the same table
+
+ DataTable ptable = parentColumns[0].Table;
+ DataTable ctable = childColumns[0].Table;
+
+ //not null check
+ //TODO: columns must belong to a table else ArgumentException
+
+
+ foreach (DataColumn pc in parentColumns)
+ {
+
+ foreach (DataColumn cc in childColumns)
+ {
+
+ }
+ }
+
+ //Tables must be from same datasets
+ if (ptable.DataSet != ctable.DataSet)
+ {
+ throw new InvalidOperationException("Tables must belong to the same dataset.");
+ }
+
+ }
+
#endregion // Constructors
+ #region Helpers
+ private void _validateRemoveParentConstraint(ConstraintCollection sender,
+ Constraint constraint, ref bool cancel, ref string failReason)
+ {
+ //if we hold a reference to the parent then cancel it
+ if (constraint == _parentUniqueConstraint)
+ {
+ cancel = true;
+ failReason = "Cannot remove UniqueConstraint because the"
+ + " ForeignKeyConstraint " + this.ConstraintName + " exists.";
+ }
+ }
+
+ //Checks to see if a related unique constraint exists
+ //if it doesn't then a unique constraint is created.
+ //if a unique constraint can't be created an exception will be thrown
+ private void _ensureUniqueConstraintExists(ConstraintCollection collection,
+ DataColumn [] parentColumns)
+ {
+ //not null
+ if (null == parentColumns) throw new ArgumentNullException(
+ "ParentColumns can't be null");
+
+ UniqueConstraint uc = null;
+
+ //see if unique constraint already exists
+ //if not create unique constraint
+ uc = UniqueConstraint.GetUniqueConstraintForColumnSet(collection, parentColumns);
+
+ if (null == uc) uc = new UniqueConstraint(parentColumns, false); //could throw
+
+ //keep reference
+ _parentUniqueConstraint = uc;
+
+ //if this unique constraint is attempted to be removed before us
+ //we can fail the validation
+ collection.ValidateRemoveConstraint += new DelegateValidateRemoveConstraint(
+ _validateRemoveParentConstraint);
+ }
+
+
+ #endregion //Helpers
+
+
#region Properites
-\r
+
public virtual AcceptRejectRule AcceptRejectRule {
- [MonoTODO]
get {
- throw new NotImplementedException ();
+ return _acceptRejectRule;
}
- [MonoTODO]
set {
- throw new NotImplementedException ();
+ _acceptRejectRule = value;
}
}
-\r
- public virtual DataColumn[] Columns {
- [MonoTODO]
+
+ public virtual Rule DeleteRule {
get {
- throw new NotImplementedException ();
+ return _deleteRule;
+ }
+
+ set {
+ _deleteRule = value;
}
}
-\r
- public virtual Rule DeleteRule {
- [MonoTODO]
+
+ public virtual Rule UpdateRule {
get {
- throw new NotImplementedException ();
+ return _updateRule;
}
- [MonoTODO]
set {
- throw new NotImplementedException ();
+ _updateRule = value;
+ }
+ }
+
+ public virtual DataColumn[] Columns {
+ get {
+ return _childColumns;
}
}
-\r
+
public virtual DataColumn[] RelatedColumns {
- [MonoTODO]
get {
- throw new NotImplementedException ();
+ return _parentColumns;
}
- }\r
-\r
+ }
+
public virtual DataTable RelatedTable {
- [MonoTODO]
get {
- throw new NotImplementedException ();
+ if (_parentColumns != null)
+ if (_parentColumns.Length > 0)
+ return _parentColumns[0].Table;
+
+ return null;
}
}
-\r
+
public override DataTable Table {
- [MonoTODO]
- get {
- throw new NotImplementedException ();
- }
- }
-\r
- public virtual Rule UpdateRule {
- [MonoTODO]
get {
- throw new NotImplementedException ();
- }
-
- [MonoTODO]
- set {
- throw new NotImplementedException ();
+ if (_childColumns != null)
+ if (_childColumns.Length > 0)
+ return _childColumns[0].Table;
+
+ return null;
}
}
+
+
#endregion // Properties
#region Methods
- [MonoTODO]\r
- public override bool Equals(object key) {
- throw new NotImplementedException ();
+ public override bool Equals(object key)
+ {
+ ForeignKeyConstraint fkc = key as ForeignKeyConstraint;
+ if (null == fkc) return false;
+
+ //if the fk constrains the same columns then they are equal
+ if (! DataColumn.AreColumnSetsTheSame( this.RelatedColumns, fkc.RelatedColumns))
+ return false;
+ if (! DataColumn.AreColumnSetsTheSame( this.Columns, fkc.Columns) )
+ return false;
+
+ return true;
}
- [MonoTODO]\r
+ [MonoTODO]
public override int GetHashCode() {
throw new NotImplementedException ();
}
+ protected internal override void AddToConstraintCollectionSetup(
+ ConstraintCollection collection)
+ {
+
+ //TODO:Should run Ctor rules again
+
+ _ensureUniqueConstraintExists(collection, _parentColumns);
+
+ }
+
+
+ [MonoTODO]
+ protected internal override void RemoveFromConstraintCollectionCleanup(
+ ConstraintCollection collection)
+ {
+ return; //no rules yet
+ }
+
+ [MonoTODO]
+ internal override void AssertConstraint()
+ {
+ //Constraint only works if both tables are part of the same dataset
+
+ //if DataSet ...
+
+ //check for orphaned children
+ //check for...
+
+ }
+
#endregion // Methods
}
namespace System.Data
{
- public class UniqueConstraint : Constraint {
+ public class UniqueConstraint : Constraint
+ {
+ private bool _isPrimaryKey = false;
+ private DataTable _dataTable; //set by ctor except when unique case
+
+ private DataColumn [] _dataColumns;
+
+ //TODO:provide helpers for this case
+ private string [] _dataColumnNames; //unique case
+
#region Constructors
- [MonoTODO]\r
public UniqueConstraint(DataColumn column) {
- throw new NotImplementedException ();
+
+ _uniqueConstraint ("", column, false);
}
- [MonoTODO]
public UniqueConstraint(DataColumn[] columns) {
-
- throw new NotImplementedException ();
+
+ _uniqueConstraint ("", columns, false);
}
- [MonoTODO]
- public UniqueConstraint(DataColumn column,\r
+ public UniqueConstraint(DataColumn column,
bool isPrimaryKey) {
- throw new NotImplementedException ();
+ _uniqueConstraint ("", column, isPrimaryKey);
}
- [MonoTODO]
public UniqueConstraint(DataColumn[] columns, bool isPrimaryKey) {
- throw new NotImplementedException ();
+ _uniqueConstraint ("", columns, isPrimaryKey);
}
- [MonoTODO]
public UniqueConstraint(string name, DataColumn column) {
- throw new NotImplementedException ();
+ _uniqueConstraint (name, column, false);
}
- [MonoTODO]
public UniqueConstraint(string name, DataColumn[] columns) {
- throw new NotImplementedException ();
+ _uniqueConstraint (name, columns, false);
}
- [MonoTODO]
- public UniqueConstraint(string name, DataColumn column,\r
+ public UniqueConstraint(string name, DataColumn column,
bool isPrimaryKey) {
- throw new NotImplementedException ();
+ _uniqueConstraint (name, column, isPrimaryKey);
}
- [MonoTODO]
- public UniqueConstraint(string name,\r
+ public UniqueConstraint(string name,
DataColumn[] columns, bool isPrimaryKey) {
- throw new NotImplementedException ();
+ _uniqueConstraint (name, columns, isPrimaryKey);
}
+ //Special case. Can only be added to the Collection with AddRange
[MonoTODO]
- public UniqueConstraint(string name,\r
+ public UniqueConstraint(string name,
string[] columnNames, bool isPrimaryKey) {
- throw new NotImplementedException ();
+ throw new NotImplementedException(); //need to finish related logic
+
+ base.ConstraintName = name;
+
+ //set unique
+ //must set unique when added to the collection
+
+ //keep list of names to resolve later
+ _dataColumnNames = columnNames;
+
+ _isPrimaryKey = isPrimaryKey;
}
+ //helper ctor
+ private void _uniqueConstraint(string name,
+ DataColumn column, bool isPrimaryKey) {
+
+ //validate
+ _validateColumn (column);
+
+ //Set Constraint Name
+ base.ConstraintName = name;
+
+ //set unique
+ column.Unique = true;
+
+ //keep reference
+ _dataColumns = new DataColumn [] {column};
+
+ //PK?
+ _isPrimaryKey = isPrimaryKey;
+
+ //Get table reference
+ _dataTable = column.Table;
+ }
+
+ //helpter ctor
+ public void _uniqueConstraint(string name,
+ DataColumn[] columns, bool isPrimaryKey) {
+
+ //validate
+ _validateColumns (columns, out _dataTable);
+
+ //Set Constraint Name
+ base.ConstraintName = name;
+
+ //set unique
+ _setColumnsUnique (columns);
+
+ //keep reference
+ _dataColumns = columns;
+
+ //PK?
+ _isPrimaryKey = isPrimaryKey;
+
+ }
+
#endregion // Constructors
+
+ #region Helpers
+ private void _setColumnsUnique(DataColumn [] columns) {
+ if (null == columns) return;
+ foreach (DataColumn col in columns) {
+ col.Unique = true;
+ }
+ }
+
+ //Validates a collection of columns with the ctor rules
+ private void _validateColumns(DataColumn [] columns, out DataTable table) {
+ table = null;
+
+ //not null
+ if (null == columns) throw new ArgumentNullException();
+
+ //check that there is at least one column
+ //LAMESPEC: not in spec
+ if (columns.Length < 1)
+ throw new InvalidConstraintException("Must be at least one column.");
+
+ DataTable compareTable = columns[0].Table;
+ //foreach
+ foreach (DataColumn col in columns){
+
+ //check individual column rules
+ _validateColumn (col);
+
+
+ //check that columns are all from the same table??
+ //LAMESPEC: not in spec
+ if (compareTable != col.Table)
+ throw new InvalidConstraintException("Columns must be from the same table.");
+
+ }
+
+ table = compareTable;
+ }
+
+ //validates a column with the ctor rules
+ private void _validateColumn(DataColumn column) {
+
+ //not null
+ if (null == column) throw new ArgumentNullException();
+
+ //column must belong to a table
+ //LAMESPEC: not in spec
+ if (null == column.Table)
+ throw new ArgumentException("Column " + column.ColumnName + " must belong to a table.");
+
+ }
+
+ internal static UniqueConstraint GetUniqueConstraintForColumnSet(ConstraintCollection collection,
+ DataColumn[] columns)
+ {
+ if (null == columns ) return null;
+
+ UniqueConstraint uniqueConstraint;
+ IEnumerator enumer = collection.GetEnumerator();
+ while (enumer.MoveNext())
+ {
+ uniqueConstraint = enumer.Current as UniqueConstraint;
+ if (uniqueConstraint != null)
+ {
+ if ( DataColumn.AreColumnSetsTheSame(uniqueConstraint.Columns, columns) )
+ {
+ return uniqueConstraint;
+ }
+ }
+ }
+ return null;
+ }
+
+
+ #endregion //Helpers
+
#region Properties
public virtual DataColumn[] Columns {
- [MonoTODO]
get {
- throw new NotImplementedException ();
+ return _dataColumns;
}
}
public bool IsPrimaryKey {
- [MonoTODO]
get {
- throw new NotImplementedException ();
+ return _isPrimaryKey;
}
}
public override DataTable Table {
- [MonoTODO]
get {
- throw new NotImplementedException ();
+ return _dataTable;
}
}
#region Methods
public override bool Equals(object key2) {
+
UniqueConstraint cst = key2 as UniqueConstraint;
if (null == cst) return false;
//according to spec if the cols are equal
//then two UniqueConstraints are equal
- bool found = false;
- foreach (DataColumn thisCol in this.Columns) {
- found = false;
- foreach (DataColumn col in cst.Columns) {
- if (thisCol == col)
- found = true;
- }
- if (false == found) return false;
- }
+ return DataColumn.AreColumnSetsTheSame(cst.Columns, this.Columns);
- //if we got here then all columns were found
- return true;
-
}
[MonoTODO]
public override int GetHashCode() {
throw new NotImplementedException ();
}
+
+
+ internal protected override void AddToConstraintCollectionSetup(
+ ConstraintCollection collection)
+ {
+ //TODO:Should run Ctor rules again
+
+ //make sure a unique constraint doesn't already exists for these columns
+ UniqueConstraint uc = UniqueConstraint.GetUniqueConstraintForColumnSet(collection, this.Columns);
+ if (null != uc) throw new ArgumentException("Unique constraint already exists for these" +
+ " columns.");
+
+ }
+
+
+ internal protected override void RemoveFromConstraintCollectionCleanup(
+ ConstraintCollection collection)
+ {
+ }
+ [MonoTODO]
+ internal override void AssertConstraint()
+ {
+ //Unique?
+ }
#endregion // Methods
}
}
+2002-08-15 Franklin Wise <gracenote@earthlink.net>
+
+ * AllTests.cs: Added ForeignKeyConstraintTest to active running tests.
+
+ * NewFile: System.Data\ForeignKeyConstraintTest.cs
+
+ * System.Data\ConstraintTest: Added new test.
+
+ * System.Data\UniqueConstraintTest: Added more tests.
+
2002-08-14 Daniel Morgan <danmorg@sc.rr.com>
* SqlSharpCli.cs: modified
suite.AddTest (new TestSuite (typeof (UniqueConstraintTest)));
suite.AddTest (new TestSuite (typeof (ConstraintTest)));
suite.AddTest (new TestSuite (typeof (ConstraintCollectionTest)));
+ suite.AddTest (new TestSuite (typeof (ForeignKeyConstraintTest)));
return suite;
}
}
public class ConstraintCollectionTest : TestCase
{
private DataTable _table;
+ private DataTable _table2;
private Constraint _constraint1;
private Constraint _constraint2;
_table = new DataTable("TestTable");
_table.Columns.Add("Col1",typeof(int));
_table.Columns.Add("Col2",typeof(int));
+ _table.Columns.Add("Col3",typeof(int));
+
+ _table2 = new DataTable("TestTable");
+ _table2.Columns.Add("Col1",typeof(int));
+ _table2.Columns.Add("Col2",typeof(int));
//Use UniqueConstraint to test Constraint Base Class
_constraint1 = new UniqueConstraint(_table.Columns[0],false);
public void TestAddExceptions()
{
ConstraintCollection col = _table.Constraints;
+
+ //null
try
{
col.Add(null);
Assertion.Fail("A1: Wrong exception type");
}
+ //duplicate name
try
{
_constraint1.ConstraintName = "Dog";
}
}
+ public void TestIndexer()
+ {
+ Constraint c1 = new UniqueConstraint(_table.Columns[0]);
+ Constraint c2 = new UniqueConstraint(_table.Columns[1]);
+
+ c1.ConstraintName = "first";
+ c2.ConstraintName = "second";
+
+
+ _table.Constraints.Add(c1);
+ _table.Constraints.Add(c2);
+
+ Assertion.AssertSame("A1", c1, _table.Constraints[0]);
+ Assertion.AssertSame("A2", c2, _table.Constraints[1]);
+
+ Assertion.AssertSame("A3", c1, _table.Constraints["first"]);
+ Assertion.AssertSame("A4", c2, _table.Constraints["sEcond"]); //case insensitive
+
+ }
+
+ public void TestIndexOf()
+ {
+ Constraint c1 = new UniqueConstraint(_table.Columns[0]);
+ Constraint c2 = new UniqueConstraint(_table.Columns[1]);
+
+ c1.ConstraintName = "first";
+ c2.ConstraintName = "second";
+
+ _table.Constraints.Add(c1);
+ _table.Constraints.Add(c2);
+
+ Assertion.AssertEquals("A1", 0, _table.Constraints.IndexOf(c1));
+ Assertion.AssertEquals("A2", 1, _table.Constraints.IndexOf(c2));
+ Assertion.AssertEquals("A3", 0, _table.Constraints.IndexOf("first"));
+ Assertion.AssertEquals("A4", 1, _table.Constraints.IndexOf("second"));
+ }
+
+ public void TestContains()
+ {
+ Constraint c1 = new UniqueConstraint(_table.Columns[0]);
+ Constraint c2 = new UniqueConstraint(_table.Columns[1]);
+
+ c1.ConstraintName = "first";
+ c2.ConstraintName = "second";
+
+ _table.Constraints.Add(c1);
+
+ Assertion.Assert("A1", _table.Constraints.Contains(c1.ConstraintName)); //true
+ Assertion.Assert("A2", _table.Constraints.Contains(c2.ConstraintName) == false); //doesn't contain
+ }
+
+ public void TestIndexerFailures()
+ {
+ _table.Constraints.Add(new UniqueConstraint(_table.Columns[0]));
+
+ //This doesn't throw
+ Assertion.AssertNull(_table.Constraints["notInCollection"]);
+
+ //Index too high
+ try
+ {
+ Constraint c = _table.Constraints[_table.Constraints.Count];
+ Assertion.Fail("B1: Failed to throw IndexOutOfRangeException.");
+ }
+ catch (IndexOutOfRangeException) {}
+ catch (AssertionFailedError exc) {throw exc;}
+ catch
+ {
+ Assertion.Fail("A1: Wrong exception type");
+ }
+
+ //Index too low
+ try
+ {
+ Constraint c = _table.Constraints[-1];
+ Assertion.Fail("B2: Failed to throw IndexOutOfRangeException.");
+ }
+ catch (IndexOutOfRangeException) {}
+ catch (AssertionFailedError exc) {throw exc;}
+ catch
+ {
+ Assertion.Fail("A2: Wrong exception type");
+ }
+
+ }
+
+ //TODO: Implementation not ready for this test yet
+// public void TestAddFkException1()
+// {
+// DataSet ds = new DataSet();
+// ds.Tables.Add(_table);
+// ds.Tables.Add(_table2);
+//
+// _table.Rows.Add(new object [] {1});
+// _table.Rows.Add(new object [] {1});
+//
+// //FKC: can't create unique constraint because duplicate values already exist
+// try
+// {
+// ForeignKeyConstraint fkc = new ForeignKeyConstraint( _table.Columns[0],
+// _table2.Columns[0]);
+//
+// _table2.Constraints.Add(fkc); //should throw
+// Assertion.Fail("B1: Failed to throw ArgumentException.");
+// }
+// catch (ArgumentException) {}
+// catch (AssertionFailedError exc) {throw exc;}
+// catch (Exception exc)
+// {
+// Assertion.Fail("A1: Wrong Exception type. " + exc.ToString());
+// }
+//
+//
+// }
+
+
+ //TODO: Implementation not ready for this test yet
+// public void TestAddFkException2()
+// {
+// //Foreign key rules only work when the tables
+// //are apart of the dataset
+// DataSet ds = new DataSet();
+// ds.Tables.Add(_table);
+// ds.Tables.Add(_table2);
+//
+// _table.Rows.Add(new object [] {1});
+//
+// // will need a matching parent value in
+// // _table
+// _table2.Rows.Add(new object [] {3});
+//
+//
+// //FKC: no matching parent value
+// try
+// {
+// ForeignKeyConstraint fkc = new ForeignKeyConstraint( _table.Columns[0],
+// _table2.Columns[0]);
+//
+// _table2.Constraints.Add(fkc); //should throw
+// Assertion.Fail("B1: Failed to throw ArgumentException.");
+// }
+// catch (ArgumentException) {}
+// catch (AssertionFailedError exc) {throw exc;}
+// catch (Exception exc)
+// {
+// Assertion.Fail("A1: Wrong Exception type. " + exc.ToString());
+// }
+//
+//
+// }
+
+
+ //TODO: Implementation not ready for this test yet
+// public void TestAddUniqueExceptions()
+// {
+//
+//
+// //UC: can't create unique constraint because duplicate values already exist
+// try
+// {
+// _table.Rows.Add(new object [] {1});
+// _table.Rows.Add(new object [] {1});
+// UniqueConstraint uc = new UniqueConstraint( _table.Columns[0]);
+//
+// _table.Constraints.Add(uc); //should throw
+// Assertion.Fail("B1: Failed to throw ArgumentException.");
+// }
+// catch (ArgumentException) {}
+// catch (AssertionFailedError exc) {throw exc;}
+// catch (Exception exc)
+// {
+// Assertion.Fail("A1: Wrong Exception type. " + exc.ToString());
+// }
+// }
+
+ public void TestAddRange()
+ {
+ }
+
+ public void TestClear()
+ {
+
+ }
+
+ public void TestCanRemove()
+ {
+
+ }
+
+ public void TestCollectionChanged()
+ {
+
+ }
+
+ public void TestRemoveAt()
+ {
+ }
+
+ public void TestRemove()
+ {
+ }
+
+
public void TestRemoveExceptions()
{
}
public void TestToString() {
- //_constraint1.ConstraintName = "Test";
+ _constraint1.ConstraintName = "Test";
Assertion.Assert("ToString is the same as constraint name.", _constraint1.ConstraintName.CompareTo( _constraint1.ToString()) == 0);
+
+ _constraint1.ConstraintName = null;
+ Assertion.AssertNotNull("ToString should return empty.",_constraint1.ToString());
}
public void TestGetExtendedProperties() {
--- /dev/null
+// ForeignKeyConstraintTest.cs - NUnit Test Cases for [explain here]
+//
+// Franklin Wise (gracenote@earthlink.net)
+//
+// (C) Franklin Wise
+//
+
+
+using NUnit.Framework;
+using System;
+using System.Data;
+
+namespace MonoTests.System.Data
+{
+
+ public class ForeignKeyConstraintTest : TestCase
+ {
+ private DataSet _ds;
+
+ //NOTE: fk constraints only work when the table is part of a DataSet
+
+ public ForeignKeyConstraintTest() : base ("MonoTests.System.Data.ForeignKeyConstraintTest") {}
+ public ForeignKeyConstraintTest(string name) : base(name) {}
+
+ protected override void SetUp()
+ {
+ _ds = new DataSet();
+
+ //Setup DataTable
+ DataTable table;
+ table = new DataTable("TestTable");
+ table.Columns.Add("Col1",typeof(int));
+ table.Columns.Add("Col2",typeof(int));
+ table.Columns.Add("Col3",typeof(int));
+
+ _ds.Tables.Add(table);
+
+ table = new DataTable("TestTable2");
+ table.Columns.Add("Col1",typeof(int));
+ table.Columns.Add("Col2",typeof(int));
+ table.Columns.Add("Col3",typeof(int));
+
+ _ds.Tables.Add(table);
+
+ }
+
+ protected override void TearDown() {}
+
+ public static ITest Suite
+ {
+ get
+ {
+ return new TestSuite(typeof(ForeignKeyConstraintTest));
+ }
+ }
+
+
+ public void TestCtorExceptions ()
+ {
+ ForeignKeyConstraint fkc;
+
+ DataTable localTable = new DataTable();
+ localTable.Columns.Add("Col1",typeof(int));
+ localTable.Columns.Add("Col2",typeof(bool));
+
+ //Null
+ try
+ {
+ fkc = new ForeignKeyConstraint((DataColumn)null,(DataColumn)null);
+ Assertion.Fail("Failed to throw ArgumentNullException.");
+ }
+ catch (ArgumentNullException) {}
+ catch (AssertionFailedError exc) {throw exc;}
+ catch (Exception exc)
+ {
+ Assertion.Fail("A1: Wrong Exception type. " + exc.ToString());
+ }
+
+ //zero length collection
+ try
+ {
+ fkc = new ForeignKeyConstraint(new DataColumn[]{},new DataColumn[]{});
+ Assertion.Fail("B1: Failed to throw ArgumentException.");
+ }
+ catch (ArgumentException) {}
+ catch (AssertionFailedError exc) {throw exc;}
+ catch (Exception exc)
+ {
+ Assertion.Fail("A1: Wrong Exception type. " + exc.ToString());
+ }
+
+ //different datasets
+ try
+ {
+ fkc = new ForeignKeyConstraint(_ds.Tables[0].Columns[0], localTable.Columns[0]);
+ Assertion.Fail("Failed to throw InvalidOperationException.");
+ }
+ catch (InvalidOperationException) {}
+ catch (AssertionFailedError exc) {throw exc;}
+ catch (Exception exc)
+ {
+ Assertion.Fail("A1: Wrong Exception type. " + exc.ToString());
+ }
+
+ //different dataTypes
+ try
+ {
+ fkc = new ForeignKeyConstraint(_ds.Tables[0].Columns[0], localTable.Columns[1]);
+ Assertion.Fail("Failed to throw InvalidOperationException.");
+ }
+ catch (InvalidOperationException) {}
+ catch (AssertionFailedError exc) {throw exc;}
+ catch (Exception exc)
+ {
+ Assertion.Fail("A1: Wrong Exception type. " + exc.ToString());
+ }
+
+
+
+
+
+ }
+ }
+}
_table = new DataTable("TestTable");
_table.Columns.Add("Col1",typeof(int));
_table.Columns.Add("Col2",typeof(int));
+ _table.Columns.Add("Col3",typeof(int));
}
_table.Columns[0], _table.Columns[1]});
Assertion.AssertSame ("B2", cst.Table, _table);
+ cst = new UniqueConstraint("MyName",_table.Columns[0],true);
+
+ //Test ctor parm set for ConstraintName & IsPrimaryKey
+ Assertion.AssertEquals("ConstraintName not set in ctor.",
+ "MyName", cst.ConstraintName);
+ Assertion.AssertEquals("IsPrimaryKey not set in ctor.",
+ true, cst.IsPrimaryKey);
}
UniqueConstraint cst = new UniqueConstraint( new DataColumn [] {
_table.Columns[0], _table.Columns[1]});
UniqueConstraint cst2 = new UniqueConstraint( new DataColumn [] {
- _table.Columns[0], _table.Columns[1]});
+ _table.Columns[1], _table.Columns[0]});
UniqueConstraint cst3 = new UniqueConstraint(_table.Columns[0]);
+ UniqueConstraint cst4 = new UniqueConstraint(_table.Columns[2]);
//true
Assertion.Assert(cst.Equals(cst2) == true);
//false
- Assertion.Assert(cst.Equals(23) == false);
- Assertion.Assert(cst.Equals(cst3) == false);
-
+ Assertion.Assert("A1", cst.Equals(23) == false);
+ Assertion.Assert("A2", cst.Equals(cst3) == false);
+ Assertion.Assert("A3", cst3.Equals(cst) == false);
+ Assertion.Assert("A4", cst.Equals(cst4) == false);
}