GetChildRows - Finding Deleted ChildRows ?

E

Eric Barr

Hi all,


I've got a scenario that i can't seem to find a way around. I have an
order/detail type setup. My Order record is unmodified, but I have
detail records that have been deleted.

When i say :
oDR_MyOrderRecord.GetChildRows("somechildRelation")

GetChildRows does not return any of the deleted rows. I have tried
using the DataRowVersion = Original syntax, and still I can't find the
child rows.

Am I doing something wrong?

Is this a hole in datasets, where i can't find the deleted child rows to
call accept changes on them ?

Or, if can't get to the child rows, shouldn't calling AcceptChanges() on
the record for the order row make the deleted rows dissapear / detach ?


Regards,
-eric
 
D

David Sceppa

Eric,

By default, the DataRow.AcceptChanges call will not cascade down to
related child rows. You can force the call to cascade down by setting the
ForeignKeyConstraint object's AcceptRejectRule property to Cascade:

MyRelation.ChildKeyConstraint.AcceptRejectRule = AcceptRejectRule.Accept

Back to the original question regarding GetChildRows and deleted rows.
The best way to access the deleted child rows would be to use a DataView.
I've included some code at the end of this post that I hope proves helpful.

David Sceppa
Microsoft
This posting is provided "AS IS" with no warranties,
and confers no rights. You assume all risk for your use.
© 2005 Microsoft Corporation. All rights reserved.

DataSet ds = new DataSet();
DataTable tblParent = ds.Tables.Add("Parent");
tblParent.Columns.Add("ParentID", typeof(int));
tblParent.LoadDataRow(new object[] {1}, true);

DataTable tblChild = ds.Tables.Add("Child");
tblChild.Columns.Add("ParentID", typeof(int));
tblChild.Columns.Add("ChildID", typeof(int));
tblChild.LoadDataRow(new object[] {1, 1}, true);
tblChild.LoadDataRow(new object[] {1, 2}, true);

ds.Relations.Add(tblParent.Columns["ParentID"],
tblChild.Columns["ParentID"]);

tblChild.Rows[1].Delete();

DataView vueParent = new DataView(tblParent);
DataView vueChildren = vueParent[0].CreateChildView(ds.Relations[0]);
vueChildren.RowStateFilter = DataViewRowState.Deleted;
foreach (DataRowView row in vueChildren)
Console.WriteLine(row["ChildID"]);
 
E

Eric Barr

David,

Thanks for the tip about accept changes. I actually have function that
takes care of accept changed (shallow vs. deep) because i flip back and
forth all the time. It would be impractical to turn the setting on/off
across the entire hierarcy of tables i'm working with.

I know I can create a dataview to get to child rows in a deleted state.
However, the problem here is that creating a dataview is way more
expensive an operation than i can afford. GetChildRows() seems to be
precalcualated when the dataset is populated. When i traced with
Devpartners GetChildRows as at least 10x faster then building a dataview
and sometimes even more if the data being searched is large enough.

So, i go back to my original scenario:

Order /Detail setup. Order record is unchanged, a detail row is marked
as deleted. Saying
OrderRow.GetChildRows("Order_has_Details")
does not give me a handle to the deleted child rows. Even saying
OrderRow.GetChildRows("Order_has_Details", Original)
does not give me a handle to the deleted child rows.

Isn't this a bug in the way data relations are hadled ? The
documentation on getChildRows is not nearly detailed enough to account
for this situation. If it isn't a bug, isn't it at least a gaping hole
in how datarelations work ?

No way to get to rows that are for the time being "soft deleted", via
the relationship sure seems like a problem to me.

Regards,
-eric



Is



David said:
Eric,

By default, the DataRow.AcceptChanges call will not cascade down to
related child rows. You can force the call to cascade down by setting the
ForeignKeyConstraint object's AcceptRejectRule property to Cascade:

MyRelation.ChildKeyConstraint.AcceptRejectRule = AcceptRejectRule.Accept

Back to the original question regarding GetChildRows and deleted rows.
The best way to access the deleted child rows would be to use a DataView.
I've included some code at the end of this post that I hope proves helpful.

David Sceppa
Microsoft
This posting is provided "AS IS" with no warranties,
and confers no rights. You assume all risk for your use.
© 2005 Microsoft Corporation. All rights reserved.

DataSet ds = new DataSet();
DataTable tblParent = ds.Tables.Add("Parent");
tblParent.Columns.Add("ParentID", typeof(int));
tblParent.LoadDataRow(new object[] {1}, true);

DataTable tblChild = ds.Tables.Add("Child");
tblChild.Columns.Add("ParentID", typeof(int));
tblChild.Columns.Add("ChildID", typeof(int));
tblChild.LoadDataRow(new object[] {1, 1}, true);
tblChild.LoadDataRow(new object[] {1, 2}, true);

ds.Relations.Add(tblParent.Columns["ParentID"],
tblChild.Columns["ParentID"]);

tblChild.Rows[1].Delete();

DataView vueParent = new DataView(tblParent);
DataView vueChildren = vueParent[0].CreateChildView(ds.Relations[0]);
vueChildren.RowStateFilter = DataViewRowState.Deleted;
foreach (DataRowView row in vueChildren)
Console.WriteLine(row["ChildID"]);
 
E

Eric Barr

David,

Thanks for the tip about accept changes. I actually have function that
takes care of accept changed (shallow vs. deep) because i flip back and
forth all the time. It would be impractical to turn the setting on/off
across the entire hierarchy of tables I'm working with.

I know I can create a data view to get to child rows in a deleted state.
However, the problem here is that creating a data view is way more
expensive an operation than i can afford. GetChildRows() seems to be
pre-calcualated when the dataset is populated. When i traced with
Dev Partners GetChildRows as at least 10x faster then building a data view
and sometimes even more if the data being searched is large enough.

So, i go back to my original scenario:

Order /Detail setup. Order record is unchanged, a detail row is marked
as deleted. Saying
OrderRow.GetChildRows("Order_has_Details")
does not give me a handle to the deleted child rows. Even saying
OrderRow.GetChildRows("Order_has_Details", Original)
does not give me a handle to the deleted child rows.

Isn't this a bug in the way data relations are handled ? The
documentation on getChildRows is not nearly detailed enough to account
for this situation. If it isn't a bug, isn't it at least a gaping hole
in how data relations work ?

No way to get to rows that are for the time being "soft deleted", via
the relationship sure seems like a problem to me.

Regards,
-eric



Is



David said:
Eric,

By default, the DataRow.AcceptChanges call will not cascade down to
related child rows. You can force the call to cascade down by setting the
ForeignKeyConstraint object's AcceptRejectRule property to Cascade:

MyRelation.ChildKeyConstraint.AcceptRejectRule = AcceptRejectRule.Accept

Back to the original question regarding GetChildRows and deleted rows.
The best way to access the deleted child rows would be to use a DataView.
I've included some code at the end of this post that I hope proves helpful.

David Sceppa
Microsoft
This posting is provided "AS IS" with no warranties,
and confers no rights. You assume all risk for your use.
© 2005 Microsoft Corporation. All rights reserved.

DataSet ds = new DataSet();
DataTable tblParent = ds.Tables.Add("Parent");
tblParent.Columns.Add("ParentID", typeof(int));
tblParent.LoadDataRow(new object[] {1}, true);

DataTable tblChild = ds.Tables.Add("Child");
tblChild.Columns.Add("ParentID", typeof(int));
tblChild.Columns.Add("ChildID", typeof(int));
tblChild.LoadDataRow(new object[] {1, 1}, true);
tblChild.LoadDataRow(new object[] {1, 2}, true);

ds.Relations.Add(tblParent.Columns["ParentID"],
tblChild.Columns["ParentID"]);

tblChild.Rows[1].Delete();

DataView vueParent = new DataView(tblParent);
DataView vueChildren = vueParent[0].CreateChildView(ds.Relations[0]);
vueChildren.RowStateFilter = DataViewRowState.Deleted;
foreach (DataRowView row in vueChildren)
Console.WriteLine(row["ChildID"]);
 
E

Eric Barr

David,

Thanks for the tip about accept changes. I actually have function that
takes care of accept changed (shallow vs. deep) because i flip back and
forth all the time. It would be impractical to turn the setting on/off
across the entire hierarchy of tables I'm working with.

I know I can create a data view to get to child rows in a deleted state.
However, the problem here is that creating a data view is way more
expensive an operation than i can afford. GetChildRows() seems to be
pre-calcualated when the dataset is populated. When i traced with
Dev Partners GetChildRows as at least 10x faster then building a data view
and sometimes even more if the data being searched is large enough.

So, i go back to my original scenario:

Order /Detail setup. Order record is unchanged, a detail row is marked
as deleted. Saying
OrderRow.GetChildRows("Order_has_Details")
does not give me a handle to the deleted child rows. Even saying
OrderRow.GetChildRows("Order_has_Details", Original)
does not give me a handle to the deleted child rows.

Isn't this a bug in the way data relations are handled ? The
documentation on getChildRows is not nearly detailed enough to account
for this situation. If it isn't a bug, isn't it at least a gaping hole
in how data relations work ?

No way to get to rows that are for the time being "soft deleted", via
the relationship sure seems like a problem to me.

Regards,
-eric



Is



David said:
Eric,

By default, the DataRow.AcceptChanges call will not cascade down to
related child rows. You can force the call to cascade down by setting the
ForeignKeyConstraint object's AcceptRejectRule property to Cascade:

MyRelation.ChildKeyConstraint.AcceptRejectRule = AcceptRejectRule.Accept

Back to the original question regarding GetChildRows and deleted rows.
The best way to access the deleted child rows would be to use a DataView.
I've included some code at the end of this post that I hope proves helpful.

David Sceppa
Microsoft
This posting is provided "AS IS" with no warranties,
and confers no rights. You assume all risk for your use.
© 2005 Microsoft Corporation. All rights reserved.

DataSet ds = new DataSet();
DataTable tblParent = ds.Tables.Add("Parent");
tblParent.Columns.Add("ParentID", typeof(int));
tblParent.LoadDataRow(new object[] {1}, true);

DataTable tblChild = ds.Tables.Add("Child");
tblChild.Columns.Add("ParentID", typeof(int));
tblChild.Columns.Add("ChildID", typeof(int));
tblChild.LoadDataRow(new object[] {1, 1}, true);
tblChild.LoadDataRow(new object[] {1, 2}, true);

ds.Relations.Add(tblParent.Columns["ParentID"],
tblChild.Columns["ParentID"]);

tblChild.Rows[1].Delete();

DataView vueParent = new DataView(tblParent);
DataView vueChildren = vueParent[0].CreateChildView(ds.Relations[0]);
vueChildren.RowStateFilter = DataViewRowState.Deleted;
foreach (DataRowView row in vueChildren)
Console.WriteLine(row["ChildID"]);
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top