[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