Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / New Users / November 2006

Tip: Looking for answers? Try searching our database.

DataAdapter.Update bug updating Child table via Relations / RowState corrupted?

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Chris Bordeman - 21 Nov 2006 20:30 GMT
Hi all.  .Net 2.0.

It seems the DataAdapter.Update Method changes the RowState of child records
to 'Modified' when updating them through a Relation.

If the child records' .RowState is "Added" or "Deleted," shouldn't they STAY
that way?  Otherwise when you try to update the child table, you get
concurrency errors (record doesn't exist to update) or records fail to
delete.

Chris B.
Dave Sexton - 21 Nov 2006 21:30 GMT
Hi Chris,

I've never observed anything like that, even when UpdateRule is set to
Cascade for ForeignKeyConstraints.

Could you post some short but complete code that reproduces the problem?

(See Jon Skeet's article, http://www.yoda.arachsys.com/csharp/complete.html 
for a description on "short but complete")

Signature

Dave Sexton

> Hi all.  .Net 2.0.
>
[quoted text clipped - 7 lines]
>
> Chris B.
Chris Bordeman - 22 Nov 2006 05:41 GMT
I'm too lazy now to work up an example project but here are some posts by
people having the same problem:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=928845&SiteID=1

Here's how to reproduce:

Create a dataset, add 2 tables and a relationship with cascading updates
between the two and add some new rows to both tables.  All rows will have a
RowStatus of 'Added'.

Use a dataadapter to update the parent table, with AcceptChangesDuringUpdate
set to false.

You'll see the RowStatus of all the rows in the child table are changed to
'Modified.'

> Hi Chris,
>
[quoted text clipped - 18 lines]
>>
>> Chris B.
Dave Sexton - 22 Nov 2006 07:00 GMT
Hi Chris,

I still can't reproduce the problem.  I followed your specifications and
wrote the following code, which results in no errors, 3 records persisted in
the parent database table and all related child records having a RowState of
Added:

// Note: I tried with an auto-increment PK and with a string PK
// and both produced the same results

DataSet data = new DataSet();

DataTable parent = data.Tables.Add("ParentTable");
DataColumn pk = parent.Columns.Add("ParentID", typeof(int));
pk.AutoIncrement = true;
pk.AllowDBNull = false;
pk.ReadOnly = true;
parent.Constraints.Add("PK_ParentID", pk, true);
parent.Columns.Add("Text", typeof(string));

DataTable child = data.Tables.Add("ChildTable");
child.Columns.Add("ChildID", typeof(string));
child.Columns.Add("ParentID", typeof(int));

ForeignKeyConstraint foreignKeyConstraint =
   (ForeignKeyConstraint) child.Constraints.Add("FK_Child_Parent",
       parent.Columns[0], child.Columns[1]);

foreignKeyConstraint.UpdateRule = Rule.Cascade;

child.Rows.Add("C1",
   parent.Rows.Add(null, "P1")["ParentID"]);
child.Rows.Add("C2",
   parent.Rows.Add(null, "P2")["ParentID"]);
child.Rows.Add("C3",
   parent.Rows.Add(null, "P3")["ParentID"]);

foreach (DataRow row in parent.Rows)
   Debug.Assert(row.RowState == DataRowState.Added);

foreach (DataRow row in child.Rows)
   Debug.Assert(row.RowState == DataRowState.Added);

using (SqlConnection connection = new SqlConnection(
   Properties.Settings.Default.TestingConnectionString))
{
   using (SqlDataAdapter adapter = new SqlDataAdapter())
   {
       using (SqlCommand command = new SqlCommand(
           @"INSERT ParentTable SELECT @Text;
               SELECT SCOPE_IDENTITY();", connection))
       {
           command.Parameters.Add("@Text", SqlDbType.NVarChar, 50, "Text");

           adapter.AcceptChangesDuringUpdate = false;
           adapter.InsertCommand = command;
           adapter.Update(parent); // parent is a DataTable
       }
   }
}

foreach (DataRow row in parent.Rows)
   // check for Modified since pk is updated by adapter
   Debug.Assert(row.RowState == DataRowState.Modified,
       row["Text"].ToString() + ": Invalid parent RowState: " +
       row.RowState.ToString());

foreach (DataRow row in child.Rows)
   Debug.Assert(row.RowState == DataRowState.Added,
       row["ChildID"].ToString() + ": Invalid child RowState: " +
       row.RowState.ToString());

MessageBox.Show("Done!");

Signature

Dave Sexton

> I'm too lazy now to work up an example project but here are some posts by
> people having the same problem:
[quoted text clipped - 34 lines]
>>>
>>> Chris B.
Bart Mermuys - 24 Nov 2006 23:33 GMT
Hi,

> I'm too lazy now to work up an example project but here are some posts by
> people having the same problem:
[quoted text clipped - 8 lines]
> Use a dataadapter to update the parent table, with
> AcceptChangesDuringUpdate set to false.

The DataAdapter will obviously use your InsertCommand foreach Added row, but
it does it like this:

-> RowState.Added
1) setup command/set parameter values ...etc...
2) execute InsertCommand
3) if the InsertCommand.UpdatedRowSource = FirstReturnedRecord
(which is quite normal if you use autonumber keys), then it will _always_
call AcceptChanges
-> RowState.Unmodified
4) load the values from FirstReturnedRecord into the DataRow
(this will set the new pk)
-> RowState.Modified
5) if AcceptChangesDuringUpdate = true, call AcceptChanges again
-> RowState.Unmodified

So, if you use an InsertCommand which retrieves the autonumber key, then
turning off AcceptChangesDuringUpdate will make the RowState go from Added
to Modified.

And if the ForeignKeyConstraint has AcceptRejectRule=Cascade then a similar
thing will happen for the related child rows:  when AcceptChanges is called
on the parent row (3) it will cascade and call AcceptChanges on the child
row, changing its state to unmodifed, then when the new key is retrieved (4)
it will propagate the key to the child row (UpdateRule=Cascade), making the
child row enter a modified state.

Offcourse i don't know whether you are using AcceptRejectRule=Cascade but if
you are you should probely not, there are very few situations where this is
wanted.

HTH,
Greetings

> You'll see the RowStatus of all the rows in the child table are changed to
> 'Modified.'
[quoted text clipped - 21 lines]
>>>
>>> Chris B.
Chris Bordeman - 25 Nov 2006 02:38 GMT
Bart, I had the relation on Accept/Reject Cascade, set it to None and it
still didn't fix.  But the following combination worked.

"Both Relation and Foreign Key constraint"
Accept/Reject rule to None
Uncheck "Nested Relation"

Thanks Bart.

> Hi,
>
[quoted text clipped - 70 lines]
>>>>
>>>> Chris B.
Dave Sexton - 26 Nov 2006 01:08 GMT
Hi Chris,

A ForeignKeyConstraint with the UpdateRule set to Cascade shouldn't have any
effect, as I've already mentioned.  Take a look at the code in my other
response and you'll see that I used Cascade just as you mentioned and the
RowState remains as Added for related child records.

You may want to post a short code example of the problem you are having if
my code doesn't help you.

Signature

Dave Sexton

> Bart, I had the relation on Accept/Reject Cascade, set it to None and it
> still didn't fix.  But the following combination worked.
[quoted text clipped - 80 lines]
>>>>>
>>>>> Chris B.
Dave Sexton - 26 Nov 2006 01:29 GMT
Hi Chris,

I didn't read "AcceptRejectRule" - I just assumed "UpdateRule".  My example
doesn't really apply.

Signature

Dave Sexton

> Hi Chris,
>
[quoted text clipped - 91 lines]
>>>>>>
>>>>>> Chris B.
Bart Mermuys - 26 Nov 2006 21:43 GMT
Hi,

> Bart, I had the relation on Accept/Reject Cascade, set it to None and it
> still didn't fix.  But the following combination worked.
>
> "Both Relation and Foreign Key constraint"
> Accept/Reject rule to None
> Uncheck "Nested Relation"

AFAIK "Nested Relation" had nothing to do with it.  "Nested Relation" only
applies to the xml representation of the DataSet (either WriteXML or
XmlDataDocument), if Nested is true, then the child elements will be nested
inside the parent elements.

HTH,
Greetings

> Thanks Bart.
>
[quoted text clipped - 73 lines]
>>>>>
>>>>> Chris B.
Cor Ligthert [MVP] - 22 Nov 2006 04:44 GMT
Chirs,

I saw the same as Dave, to show he is not the only one.

Cor

> Hi all.  .Net 2.0.
>
[quoted text clipped - 7 lines]
>
> Chris B.

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.