2004-03-10 Umadevi S (sumadevi@novell.com)
[mono.git] / mcs / class / System.Data / System.Data / DataRowCollection.cs
index dd7eebe611fd1e31e383584354c664a86e6ab1fb..1debc20ca4260867b88ff1a61fa4c01d64b1c999 100644 (file)
@@ -64,8 +64,9 @@ namespace System.Data
 
                        if (row.Table != this.table)
                                throw new ArgumentException ("This row already belongs to another table.");
-
-                       if (list.IndexOf(row) != -1)
+                       
+                       // If row id is not -1, we know that it is in the collection.
+                       if (row.RowID != -1)
                                throw new ArgumentException ("This row already belongs to this table.");
                        
 
@@ -75,6 +76,8 @@ namespace System.Data
                        
                        row.HasParentCollection = true;
                        list.Add (row);
+                       // Set the row id.
+                       row.RowID = list.Count - 1;
                        row.AttachRow ();
                        row.Table.ChangedDataRow (row, DataRowAction.Add);
                }
@@ -234,11 +237,43 @@ namespace System.Data
                {
                        if (pos < 0)
                                throw new IndexOutOfRangeException ("The row insert position " + pos + " is invalid.");
+                       
+                       if (row == null)
+                               throw new ArgumentNullException("row", "'row' argument cannot be null.");
+       
+                       if (row.Table != this.table)
+                               throw new ArgumentException ("This row already belongs to another table.");
+
+                       // If row id is not -1, we know that it is in the collection.
+                       if (row.RowID != -1)
+                               throw new ArgumentException ("This row already belongs to this table.");
+                       
+                       if ((table.DataSet == null || table.DataSet.EnforceConstraints) && !table._duringDataLoad)
+                               // we have to check that the new row doesn't colide with existing row
+                               ValidateDataRowInternal(row);
                                
                        if (pos >= list.Count)
                                list.Add (row);
                        else
                                list.Insert (pos, row);
+                               
+                       row.HasParentCollection = true;
+                       row.AttachRow ();
+                       row.Table.ChangedDataRow (row, DataRowAction.Add);
+               }
+
+               /// <summary>
+               /// Removes the specified DataRow from the internal list. Used by DataRow to commit the removing.
+               /// </summary>
+               internal void RemoveInternal (DataRow row) {
+                       if (row == null) {
+                               throw new IndexOutOfRangeException ("The given datarow is not in the current DataRowCollection.");
+                       }
+                       int index = list.IndexOf(row);
+                       if (index < 0) {
+                               throw new IndexOutOfRangeException ("The given datarow is not in the current DataRowCollection.");
+                       }
+                       list.RemoveAt(index);
                }
 
                /// <summary>
@@ -251,9 +286,11 @@ namespace System.Data
                        int index = list.IndexOf(row);
                        if (index < 0)
                                throw new IndexOutOfRangeException ("The given datarow is not in the current DataRowCollection.");
-                       table.DeletingDataRow(row, DataRowAction.Delete);
-                       list.RemoveAt(index);
-                       table.DeletedDataRow(row, DataRowAction.Delete);
+                       row.Delete();
+                       // if the row was in added state it will be in Detached state after the
+                       // delete operation, so we have to check it.
+                       if (row.RowState != DataRowState.Detached)
+                               row.AcceptChanges();
                }
 
                /// <summary>
@@ -264,9 +301,8 @@ namespace System.Data
                        if (index < 0 || index >= list.Count)
                                throw new IndexOutOfRangeException ("There is no row at position " + index + ".");
                        DataRow row = (DataRow)list [index];
-                       table.DeletingDataRow(row, DataRowAction.Delete);
-                       list.RemoveAt(index);
-                       table.DeletedDataRow(row, DataRowAction.Delete);
+                       row.Delete();
+                       row.AcceptChanges();
                }
 
                ///<summary>
@@ -278,17 +314,46 @@ namespace System.Data
                {
                        //first check for null violations.
                        row.CheckNullConstraints();
-                       //FIXME: this validates constraints in the order they appear
-                       //in the collection. Most probably we need to do it in a 
-                       //specific order like unique/primary keys first, then Foreignkeys, etc
-                       foreach(Constraint constraint in table.Constraints)
-                       {
-                               constraint.AssertConstraint(row);
+                       // This validates constraints in the specific order : 
+                       // first unique/primary keys first, then Foreignkeys, etc
+                       ArrayList uniqueConstraintsDone = new ArrayList();
+                       ArrayList foreignKeyConstraintsDone = new ArrayList();
+                       try {
+                               foreach(Constraint constraint in table.Constraints.UniqueConstraints) {
+                                       constraint.AssertConstraint(row);
+                                       uniqueConstraintsDone.Add(constraint);
+                               }
+                       
+                               foreach(Constraint constraint in table.Constraints.ForeignKeyConstraints) {
+                                       constraint.AssertConstraint(row);
+                                       foreignKeyConstraintsDone.Add(constraint);
+                               }
+                       }
+                       // if one of the AssertConstraint failed - we need to "rollback" all the changes
+                       // caused by AssertCoinstraint calls already succeeded
+                       catch(ConstraintException e) {
+                               RollbackAsserts(row,foreignKeyConstraintsDone,uniqueConstraintsDone);
+                               throw e;
+                       }
+                       catch(InvalidConstraintException e) {   
+                               RollbackAsserts(row,foreignKeyConstraintsDone,uniqueConstraintsDone);
+                               throw e;
                        }
-
                }
-               
-       }
 
+               private void RollbackAsserts(DataRow row,ICollection foreignKeyConstraintsDone,
+                       ICollection uniqueConstraintsDone)
+               {
+                       // if any of constraints assert failed - 
+                       // we have to rollback all the asserts scceeded
+                       // on order reverse to thier original execution
+                       foreach(Constraint constraint in foreignKeyConstraintsDone) {
+                               constraint.RollbackAssert(row);
+                       }
 
+                       foreach(Constraint constraint in uniqueConstraintsDone) {
+                               constraint.RollbackAssert(row);
+                       }
+               }
+       }
 }