DataTable.RowChanged when row added: GetChanges issue

S

Sorin Dolha

Hello,

This is probably a known issue or a FAQ. However, I could not find a
straight answer to the question, or a nice workaround, so I appologize if
this was answered before (in that case, I would appreciate if someone will
provide a link to a previous related thread or article).

I have a DataSet containing several tables. I am listening to
DataTable.RowChanged event to listen to row additions and changes, and to
DataTable.RowDeleted event of those tables to listen to row deletions. Both
events are triggering the same method that is using DataSet.GetChanges()
method to get all the changes made to the DataSet. For row changes and
deletions, everything is correct (the changes/deletions are returned by the
GetChanges() method as appropriate), but for row additions, the GetChanges()
returns null (or a dataset that does not contain the newly added row).

Therefore, believe that the RowChanged event is triggered just before adding
the row to the DataSet, and not after. However, there is no RowAdded event
or something similar that would allow me to GetChanges() immediately after a
row was added to the collection.

Is this a bug, or is it designed this way? If the latter, can you please
provide reasons why this design was chosen? Any known workarounds?

Workarounds that I have thought of:

1. Not thread-safe:

Within the RowChanged event handler, when DataRowAction is equal to Add,
create and start a new thread using a method that actually get changes()
later (when hopefully the DataSet will have been added the new row to the
collection);

2. Thread-safe:

Within the RowChanged event handler, when DataRowAction is equal to Add, get
DataSet changes by calling code like this:

DataSet ds = dataSet.GetChanges();
if (ds==null) ds = dataSet.Clone();
ds.EnforceConstraints = false;
ds.Tables[e.Row.Table.TableName].Rows.Add(e.Row.ItemArray);
//use ds as the changes

Both workarounds are not nice, in my opinion, therefore I am currently
looking for a better solution. Is ADO .NET 2.0 coming with an changes in the
way DataTable events are provided and raised?

Thank you,

Sorin Dolha
MCAD, MCSD .NET
 
A

Adrian Moore

Sorin

I tried the following test:

Imports System.Data

Module Module1

Sub Main()

Dim ds As New DataSet

Dim dt As New DataTable

dt.Columns.Add("test")

ds.Tables.Add(dt)

AddHandler dt.RowChanged, AddressOf RowChanged

Dim dr As DataRow = dt.NewRow

dr(0) = "Hi"

dt.Rows.Add(dr)

End Sub

Sub RowChanged(ByVal sender As Object, ByVal e As
System.Data.DataRowChangeEventArgs)

If e.Action = DataRowAction.Add Then

Debug.WriteLine(e.Row.Table.Rows.Count)

End If

End Sub

End Module

The Debug statement printed 1 indicating the row was present in the table
before the RowChanged event was fired. Admittingly, I'm using .NET 2.0, but
I don't believe this has changed since 1.1 since I have similar code working
there too.

Let me know if I'm missing the point.

Ad.





Sorin Dolha said:
Hello,

This is probably a known issue or a FAQ. However, I could not find a
straight answer to the question, or a nice workaround, so I appologize if
this was answered before (in that case, I would appreciate if someone will
provide a link to a previous related thread or article).

I have a DataSet containing several tables. I am listening to
DataTable.RowChanged event to listen to row additions and changes, and to
DataTable.RowDeleted event of those tables to listen to row deletions.
Both events are triggering the same method that is using
DataSet.GetChanges() method to get all the changes made to the DataSet.
For row changes and deletions, everything is correct (the
changes/deletions are returned by the GetChanges() method as appropriate),
but for row additions, the GetChanges() returns null (or a dataset that
does not contain the newly added row).

Therefore, believe that the RowChanged event is triggered just before
adding the row to the DataSet, and not after. However, there is no
RowAdded event or something similar that would allow me to GetChanges()
immediately after a row was added to the collection.

Is this a bug, or is it designed this way? If the latter, can you please
provide reasons why this design was chosen? Any known workarounds?

Workarounds that I have thought of:

1. Not thread-safe:

Within the RowChanged event handler, when DataRowAction is equal to Add,
create and start a new thread using a method that actually get changes()
later (when hopefully the DataSet will have been added the new row to the
collection);

2. Thread-safe:

Within the RowChanged event handler, when DataRowAction is equal to Add,
get DataSet changes by calling code like this:

DataSet ds = dataSet.GetChanges();
if (ds==null) ds = dataSet.Clone();
ds.EnforceConstraints = false;
ds.Tables[e.Row.Table.TableName].Rows.Add(e.Row.ItemArray);
//use ds as the changes

Both workarounds are not nice, in my opinion, therefore I am currently
looking for a better solution. Is ADO .NET 2.0 coming with an changes in
the way DataTable events are provided and raised?

Thank you,

Sorin Dolha
MCAD, MCSD .NET
 
S

Sorin Dolha

Can you please change the line Debug.WriteLine(e.Row.Table.Rows.Count) into:

Debug.WriteLine(ds.GetChanges() != null)

and test this way? (Note that you will also need to move ds declaration from
the local method to the class scope.)

Is this result also "true"? It should be true, but I tested in ADO .NET 1.1
and it is not; also in my test on 1.1 with your code, the value was 0 not 1.

Hopefully this is a correction for .NET 2.0, test it yourself on 1.1 if you
want (see the attachment for my sample test code). But I still need a nice
workaround (if any exists) for 1.1, because you know, the customers do not
yet want to accept 2.0 being still in beta...

Thanks,

---
Sorin Dolha

------------

Adrian Moore said:
Sorin

I tried the following test:

Imports System.Data

Module Module1

Sub Main()

Dim ds As New DataSet

Dim dt As New DataTable

dt.Columns.Add("test")

ds.Tables.Add(dt)

AddHandler dt.RowChanged, AddressOf RowChanged

Dim dr As DataRow = dt.NewRow

dr(0) = "Hi"

dt.Rows.Add(dr)

End Sub

Sub RowChanged(ByVal sender As Object, ByVal e As
System.Data.DataRowChangeEventArgs)

If e.Action = DataRowAction.Add Then

Debug.WriteLine(e.Row.Table.Rows.Count)

End If

End Sub

End Module

The Debug statement printed 1 indicating the row was present in the table
before the RowChanged event was fired. Admittingly, I'm using .NET 2.0,
but
I don't believe this has changed since 1.1 since I have similar code
working
there too.

Let me know if I'm missing the point.

Ad.





Sorin Dolha said:
Hello,

This is probably a known issue or a FAQ. However, I could not find a
straight answer to the question, or a nice workaround, so I appologize if
this was answered before (in that case, I would appreciate if someone
will
provide a link to a previous related thread or article).

I have a DataSet containing several tables. I am listening to
DataTable.RowChanged event to listen to row additions and changes, and to
DataTable.RowDeleted event of those tables to listen to row deletions.
Both events are triggering the same method that is using
DataSet.GetChanges() method to get all the changes made to the DataSet.
For row changes and deletions, everything is correct (the
changes/deletions are returned by the GetChanges() method as
appropriate),
but for row additions, the GetChanges() returns null (or a dataset that
does not contain the newly added row).

Therefore, believe that the RowChanged event is triggered just before
adding the row to the DataSet, and not after. However, there is no
RowAdded event or something similar that would allow me to GetChanges()
immediately after a row was added to the collection.

Is this a bug, or is it designed this way? If the latter, can you please
provide reasons why this design was chosen? Any known workarounds?

Workarounds that I have thought of:

1. Not thread-safe:

Within the RowChanged event handler, when DataRowAction is equal to Add,
create and start a new thread using a method that actually get changes()
later (when hopefully the DataSet will have been added the new row to the
collection);

2. Thread-safe:

Within the RowChanged event handler, when DataRowAction is equal to Add,
get DataSet changes by calling code like this:

DataSet ds = dataSet.GetChanges();
if (ds==null) ds = dataSet.Clone();
ds.EnforceConstraints = false;
ds.Tables[e.Row.Table.TableName].Rows.Add(e.Row.ItemArray);
//use ds as the changes

Both workarounds are not nice, in my opinion, therefore I am currently
looking for a better solution. Is ADO .NET 2.0 coming with an changes in
the way DataTable events are provided and raised?

Thank you,

Sorin Dolha
MCAD, MCSD .NET
 
K

Kevin Yu [MSFT]

Hi Sorin,

First of all, I would like to confirm my understanding of your issue. From
your description, I understand that when you add a new row to a DataTable,
the added row cannot be get using GetChanges in the RowChanged event. If
there is any misunderstanding, please feel free to let me know.

Thanks for your repro code. Based on my research, this is a known issue
which has been fixed in .NET framework 2.0. However, in .NET framework 1.0
and 1.1, it hasn't been fixed. In this case, we have no better workarounds
that you do. I suggest you try to contact Microsoft PSS to see if they can
work out a hotfix for you, since this is a known bug. Here is the contact
information.

http://support.microsoft.com/common/international.aspx?rdpath=gp;en-us;offer
prophone

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
A

Adrian Moore

I ran the attached file, the results using 2.0 Beta 2 are:

1
false

I added the following to the RowChanged event handler:

Debug.WriteLine(e.Row.Table.GetChanges() != null);

Debug.WriteLine(e.Row.RowState);

The results are:

True

Added

So, I'd say its a bug that DataSet doesn't report a change, but the
DataTable does.

Hope this helps

Ad.

Sorin Dolha said:
Can you please change the line Debug.WriteLine(e.Row.Table.Rows.Count)
into:

Debug.WriteLine(ds.GetChanges() != null)

and test this way? (Note that you will also need to move ds declaration
from the local method to the class scope.)

Is this result also "true"? It should be true, but I tested in ADO .NET
1.1 and it is not; also in my test on 1.1 with your code, the value was 0
not 1.

Hopefully this is a correction for .NET 2.0, test it yourself on 1.1 if
you want (see the attachment for my sample test code). But I still need a
nice workaround (if any exists) for 1.1, because you know, the customers
do not yet want to accept 2.0 being still in beta...

Thanks,

---
Sorin Dolha

------------

Adrian Moore said:
Sorin

I tried the following test:

Imports System.Data

Module Module1

Sub Main()

Dim ds As New DataSet

Dim dt As New DataTable

dt.Columns.Add("test")

ds.Tables.Add(dt)

AddHandler dt.RowChanged, AddressOf RowChanged

Dim dr As DataRow = dt.NewRow

dr(0) = "Hi"

dt.Rows.Add(dr)

End Sub

Sub RowChanged(ByVal sender As Object, ByVal e As
System.Data.DataRowChangeEventArgs)

If e.Action = DataRowAction.Add Then

Debug.WriteLine(e.Row.Table.Rows.Count)

End If

End Sub

End Module

The Debug statement printed 1 indicating the row was present in the table
before the RowChanged event was fired. Admittingly, I'm using .NET 2.0,
but
I don't believe this has changed since 1.1 since I have similar code
working
there too.

Let me know if I'm missing the point.

Ad.





Sorin Dolha said:
Hello,

This is probably a known issue or a FAQ. However, I could not find a
straight answer to the question, or a nice workaround, so I appologize
if
this was answered before (in that case, I would appreciate if someone
will
provide a link to a previous related thread or article).

I have a DataSet containing several tables. I am listening to
DataTable.RowChanged event to listen to row additions and changes, and
to
DataTable.RowDeleted event of those tables to listen to row deletions.
Both events are triggering the same method that is using
DataSet.GetChanges() method to get all the changes made to the DataSet.
For row changes and deletions, everything is correct (the
changes/deletions are returned by the GetChanges() method as
appropriate),
but for row additions, the GetChanges() returns null (or a dataset that
does not contain the newly added row).

Therefore, believe that the RowChanged event is triggered just before
adding the row to the DataSet, and not after. However, there is no
RowAdded event or something similar that would allow me to GetChanges()
immediately after a row was added to the collection.

Is this a bug, or is it designed this way? If the latter, can you please
provide reasons why this design was chosen? Any known workarounds?

Workarounds that I have thought of:

1. Not thread-safe:

Within the RowChanged event handler, when DataRowAction is equal to Add,
create and start a new thread using a method that actually get changes()
later (when hopefully the DataSet will have been added the new row to
the
collection);

2. Thread-safe:

Within the RowChanged event handler, when DataRowAction is equal to Add,
get DataSet changes by calling code like this:

DataSet ds = dataSet.GetChanges();
if (ds==null) ds = dataSet.Clone();
ds.EnforceConstraints = false;
ds.Tables[e.Row.Table.TableName].Rows.Add(e.Row.ItemArray);
//use ds as the changes

Both workarounds are not nice, in my opinion, therefore I am currently
looking for a better solution. Is ADO .NET 2.0 coming with an changes in
the way DataTable events are provided and raised?

Thank you,

Sorin Dolha
MCAD, MCSD .NET
 

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