[Mono-bugs] [Bug 75227][Nor] Changed - DataSet.GetChanges() fails when dataset includes deleted rows

bugzilla-daemon at bugzilla.ximian.com bugzilla-daemon at bugzilla.ximian.com
Fri Jun 10 21:39:47 EDT 2005


Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.

Changed by george.barbarosie at gmail.com.

http://bugzilla.ximian.com/show_bug.cgi?id=75227

--- shadow/75227	2005-06-10 20:37:35.000000000 -0400
+++ shadow/75227.tmp.3472	2005-06-10 21:39:47.000000000 -0400
@@ -1,14 +1,14 @@
 Bug#: 75227
 Product: Mono: Class Libraries
 Version: 1.1
-OS: 
+OS: unknown
 OS Details: 
 Status: NEW   
 Resolution: 
-Severity: 
+Severity: Unknown
 Priority: Normal
 Component: Sys.Data
 AssignedTo: mono-bugs at ximian.com                            
 ReportedBy: george.barbarosie at gmail.com               
 QAContact: mono-bugs at ximian.com
 TargetMilestone: ---
@@ -113,6 +113,176 @@
 in <0x000b6> System.Data.DataSet:AddChangedRow
 (System.Collections.Hashtable addedRows, System.Data.DataTable copyTable,
 System.Data.DataRow row)
 in <0x00148> System.Data.DataSet:GetChanges (DataRowState rowStates)
 in <0x0000f> System.Data.DataSet:GetChanges ()
 in <0x00514> Test:Main ()
+
+------- Additional Comments From george.barbarosie at gmail.com  2005-06-10 21:39 -------
+This actually goes deep into the current state of System.Data. 
+
+Problem 1: in GetChanges()/AddChangedRow(), a row can be deleted (only
+Original version available) or modified (both versions available, each
+pointing to a different parent row for a given relation). Should
+GetChanges() copy rows referred by Original versions of
+modified/deleted rows too? We need to test what MS .NET does in
+GetChanges().
+
+Assuming GetChanges() needs to copy rows referred by original versions
+too, a patch for the first problem is:
+
+Index: System.Data/DataSet.cs
+===================================================================
+--- System.Data/DataSet.cs      (revision 45791)
++++ System.Data/DataSet.cs      (working copy)
+@@ -502,12 +502,24 @@
+                        if (addedRows.ContainsKey (row)) return;
+
+                        foreach (DataRelation relation in
+row.Table.ParentRelations) {
+-                               DataRow parent = row.GetParentRow
+(relation);
+-                               if (parent == null)
+-                                       continue;
+-                               // add the parent row
+-                               DataTable parentCopyTable =
+copyTable.DataSet.Tables [parent.Table.TableName];
+-                               AddChangedRow (addedRows,
+parentCopyTable, parent);
++                               DataRow original=null, current=null;
++                               /* get the parent of the original row
+version */
++                               if
+(row.RowState==DataRowState.Unchanged ||
++                                              
+row.RowState==DataRowState.Modified ||
++                                              
+row.RowState==DataRowState.Deleted)
++                                       original = row.GetParentRow
+(relation, DataRowVersion.Original);
++                               /* get the parent of the
+modified/added row version */
++                               if (row.RowState==DataRowState.Modified ||
++                                              
+row.RowState==DataRowState.Added)
++                                       current = row.GetParentRow
+(relation, DataRowVersion.Current);
++                               /* they may be the same */
++                               if (original==current) current=null;
++                               // add the parent row(s)
++                               DataTable parentCopyTable =
+copyTable.DataSet.Tables [relation.ParentTable.TableName];
++                               if (original!=null)
++                                       AddChangedRow (addedRows,
+parentCopyTable, original);
++                               if (current!=null)
++                                       AddChangedRow (addedRows,
+parentCopyTable, current);
+                        }
+
+                        // add the current row
+
+Assuming we don't need to copy rows referred by original versions,
+patch would be:
+
+Index: System.Data/DataSet.cs
+===================================================================
+--- System.Data/DataSet.cs      (revision 45791)
++++ System.Data/DataSet.cs      (working copy)
+@@ -501,14 +501,15 @@
+                {
+                        if (addedRows.ContainsKey (row)) return;
+
+-                       foreach (DataRelation relation in
+row.Table.ParentRelations) {
+-                               DataRow parent = row.GetParentRow
+(relation);
+-                               if (parent == null)
+-                                       continue;
+-                               // add the parent row
+-                               DataTable parentCopyTable =
+copyTable.DataSet.Tables [parent.Table.TableName];
+-                               AddChangedRow (addedRows,
+parentCopyTable, parent);
+-                       }
++                       if (row.RowState!=DataRowState.Deleted)
++                               foreach (DataRelation relation in
+row.Table.ParentRelations) {
++                                       DataRow parent =
+row.GetParentRow (relation);
++                                       if (parent == null)
++                                               continue;
++                                       // add the parent row
++                                       DataTable parentCopyTable =
+copyTable.DataSet.Tables [parent.Table.TableName];
++                                       AddChangedRow (addedRows,
+parentCopyTable, parent);
++                               }
+
+                        // add the current row
+                        DataRow newRow = copyTable.NewNotInitializedRow();
+
+After applying either of the two patches, testcase output becomes:
+
+Exception caught (1):
+System.Data.DeletedRowInaccessibleException: Deleted row information
+cannot be accessed through the row.
+in <0x001c9> System.Data.DataRow:get_Item (Int32 columnIndex,
+DataRowVersion version)
+in <0x0004a> System.Data.DataRow:get_Item (System.Data.DataColumn
+column, DataRowVersion version)
+in <0x00022> System.Data.DataRow:IsNull (System.Data.DataColumn
+column, DataRowVersion version)
+in <0x00015> System.Data.DataRow:IsNull (System.Data.DataColumn column)
+in <0x0003a> System.Data.DataRow:IsNullColumns
+(System.Data.DataColumn[] columns)
+in <0x000e7> System.Data.ForeignKeyConstraint:IsConstraintViolated ()
+in <0x0000b> System.Data.Constraint:AssertConstraint ()
+in <0x00116> System.Data.DataSet:InternalEnforceConstraints (Boolean
+value, Boolean resetIndexes)
+in <0x00014> System.Data.DataSet:set_EnforceConstraints (Boolean value)
+in <0x001b2> System.Data.DataSet:GetChanges (DataRowState rowStates)
+in <0x0000f> System.Data.DataSet:GetChanges ()
+in <0x00457> Test:Main ()
+Exception caught (2):
+System.Data.DeletedRowInaccessibleException: Deleted row information
+cannot be accessed through the row.
+in <0x001c9> System.Data.DataRow:get_Item (Int32 columnIndex,
+DataRowVersion version)
+in <0x0004a> System.Data.DataRow:get_Item (System.Data.DataColumn
+column, DataRowVersion version)
+in <0x00022> System.Data.DataRow:IsNull (System.Data.DataColumn
+column, DataRowVersion version)
+in <0x00015> System.Data.DataRow:IsNull (System.Data.DataColumn column)
+in <0x0003a> System.Data.DataRow:IsNullColumns
+(System.Data.DataColumn[] columns)
+in <0x000e7> System.Data.ForeignKeyConstraint:IsConstraintViolated ()
+in <0x0000b> System.Data.Constraint:AssertConstraint ()
+in <0x00116> System.Data.DataSet:InternalEnforceConstraints (Boolean
+value, Boolean resetIndexes)
+in <0x00014> System.Data.DataSet:set_EnforceConstraints (Boolean value)
+in <0x001b2> System.Data.DataSet:GetChanges (DataRowState rowStates)
+in <0x0000f> System.Data.DataSet:GetChanges ()
+in <0x00514> Test:Main ()
+
+Problem 2: Should foreign key constraints be checked for deleted rows
+too? If so, should they be checked for original versions of modified
+rows too? Aagain, this needs to be tested on MS .NET; but my guess
+would be that it's overkill to check Original versions of
+modified/deleted rows too. Anyways In case we need to check them, the
+patch gets more complicated than the one-liner I have prepared below:
+
+Index: System.Data/ForeignKeyConstraint.cs
+===================================================================
+--- System.Data/ForeignKeyConstraint.cs (revision 45791)
++++ System.Data/ForeignKeyConstraint.cs (working copy)
+@@ -479,6 +479,7 @@
+
+                        bool hasErrors = false;
+                        foreach (DataRow row in Table.Rows) {
++                               if
+(row.RowState==DataRowState.Deleted) continue;
+                                // first we check if all values in
+_childColumns place are nulls.
+                                // if yes we return.
+                                if (row.IsNullColumns(_childColumns))
+


More information about the mono-bugs mailing list