Breaking change in .NET 1.1 SP1 DataTable - Repro provided

U

Urs Eichmann

The following piece of code will run fine in .NET 1.1 without SP1, but
will throw a NullReferenceException in SP1. Sadly, our app no longer
runs with SP1, since it uses the same pattern (changing another row of
data inside a ListChanged event of a DataView).

Could please someone from Microsoft confirm this as a bug, and/or
provide a workaround?

Regards,
Urs


run the following as a console app:

[VB.NET]

Imports System.Data

Module Module1

Private dt As DataTable
Private b As Boolean

Sub Main()

dt = New System.Data.DataTable
dt.Columns.Add("Col1", GetType(String))
dt.Columns.Add("Col2", GetType(String))

Dim dv As New DataView(dt, "", "Col1",
DataViewRowState.CurrentRows)
AddHandler dv.ListChanged, AddressOf OnListchanged
Dim dv2 As New DataView(dt, "", "Col2",
DataViewRowState.CurrentRows)
AddHandler dv2.ListChanged, AddressOf OnListchanged

dt.Rows.Add(New Object() {"a", "b"}) ' NullRefException will be
thrown here

End Sub

Private Sub OnListchanged(ByVal s As Object, ByVal e As
System.ComponentModel.ListChangedEventArgs)

If b Then Return
b = True ' don't want recursive calling

dt.Rows.Add(New Object() {"c", "d"})

End Sub

End Module
 
A

Angel Saenz-Badillos[MS]

Urs,
Thanks for posting this, the DataTable is not really my area but I have
forwarded your post and I will let you know as soon as I get any info.

--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging about ADO.NET: http://weblogs.asp.net/angelsb/
 
A

Angel Saenz-Badillos[MS]

Uris,
This is the response that I got from the dataset team:
"This is an unsupported scenario. Any "write" operations on DataSet in an
event handler will result in an unpredictable behavior.
I'd suggest an alternative way of solving his scenario."

I am not sure of what they mean with alternative solution, but it is true
that "touching" the datatable in multiple threads is not supported. You can
probably get arround this limitation by binding on the UI thread before
calling the Add method with something like this (please excuse the code
hack, I am doing copy paste from a c# project I had laying arround,
hopefully you can get the idea of what to look for from here). The basic
concept is that you can only call datatable add on the same thread in which
you created the datatable, in this case we assume you created it on the main
thread.


delegate void UICallback( object param );

void ReBindOnUIThread( object param )
{
//This method will run in the main thread, we can touch the DataTable
here:
dt.Rows.Add(New Object() {"c", "d"})
}

Private Sub OnListchanged(ByVal s As Object, ByVal e As
System.ComponentModel.ListChangedEventArgs)

If b Then Return
b = True ' don't want recursive calling
//you can't touch the datatable here since we are in a different
thread
//dt.Rows.Add(New Object() {"c", "d"})
//instead we rebind on the ui thread using the delegate
this.Invoke( new UICallback( ReBindOnUIThread ), new object[] {
<myobject>} );

End Sub

--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging about ADO.NET: http://weblogs.asp.net/angelsb/

Urs Eichmann said:
The following piece of code will run fine in .NET 1.1 without SP1, but
will throw a NullReferenceException in SP1. Sadly, our app no longer
runs with SP1, since it uses the same pattern (changing another row of
data inside a ListChanged event of a DataView).

Could please someone from Microsoft confirm this as a bug, and/or
provide a workaround?

Regards,
Urs


run the following as a console app:

[VB.NET]

Imports System.Data

Module Module1

Private dt As DataTable
Private b As Boolean

Sub Main()

dt = New System.Data.DataTable
dt.Columns.Add("Col1", GetType(String))
dt.Columns.Add("Col2", GetType(String))

Dim dv As New DataView(dt, "", "Col1",
DataViewRowState.CurrentRows)
AddHandler dv.ListChanged, AddressOf OnListchanged
Dim dv2 As New DataView(dt, "", "Col2",
DataViewRowState.CurrentRows)
AddHandler dv2.ListChanged, AddressOf OnListchanged

dt.Rows.Add(New Object() {"a", "b"}) ' NullRefException will be
thrown here

End Sub

Private Sub OnListchanged(ByVal s As Object, ByVal e As
System.ComponentModel.ListChangedEventArgs)

If b Then Return
b = True ' don't want recursive calling

dt.Rows.Add(New Object() {"c", "d"})

End Sub

End Module
 
G

Guest

With the installation of SP1 also an app of mine started to work badly for
other reasons: if you are interested in the thread look:
http://msdn.microsoft.com/communiti...-E56902048BAD&dglist=&ptlist=&exp=&sloc=en-us

If you have any suggestion...

Angel Saenz-Badillos said:
Uris,
This is the response that I got from the dataset team:
"This is an unsupported scenario. Any "write" operations on DataSet in an
event handler will result in an unpredictable behavior.
I'd suggest an alternative way of solving his scenario."

I am not sure of what they mean with alternative solution, but it is true
that "touching" the datatable in multiple threads is not supported. You can
probably get arround this limitation by binding on the UI thread before
calling the Add method with something like this (please excuse the code
hack, I am doing copy paste from a c# project I had laying arround,
hopefully you can get the idea of what to look for from here). The basic
concept is that you can only call datatable add on the same thread in which
you created the datatable, in this case we assume you created it on the main
thread.


delegate void UICallback( object param );

void ReBindOnUIThread( object param )
{
//This method will run in the main thread, we can touch the DataTable
here:
dt.Rows.Add(New Object() {"c", "d"})
}

Private Sub OnListchanged(ByVal s As Object, ByVal e As
System.ComponentModel.ListChangedEventArgs)

If b Then Return
b = True ' don't want recursive calling
//you can't touch the datatable here since we are in a different
thread
//dt.Rows.Add(New Object() {"c", "d"})
//instead we rebind on the ui thread using the delegate
this.Invoke( new UICallback( ReBindOnUIThread ), new object[] {
<myobject>} );

End Sub

--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging about ADO.NET: http://weblogs.asp.net/angelsb/

Urs Eichmann said:
The following piece of code will run fine in .NET 1.1 without SP1, but
will throw a NullReferenceException in SP1. Sadly, our app no longer
runs with SP1, since it uses the same pattern (changing another row of
data inside a ListChanged event of a DataView).

Could please someone from Microsoft confirm this as a bug, and/or
provide a workaround?

Regards,
Urs


run the following as a console app:

[VB.NET]

Imports System.Data

Module Module1

Private dt As DataTable
Private b As Boolean

Sub Main()

dt = New System.Data.DataTable
dt.Columns.Add("Col1", GetType(String))
dt.Columns.Add("Col2", GetType(String))

Dim dv As New DataView(dt, "", "Col1",
DataViewRowState.CurrentRows)
AddHandler dv.ListChanged, AddressOf OnListchanged
Dim dv2 As New DataView(dt, "", "Col2",
DataViewRowState.CurrentRows)
AddHandler dv2.ListChanged, AddressOf OnListchanged

dt.Rows.Add(New Object() {"a", "b"}) ' NullRefException will be
thrown here

End Sub

Private Sub OnListchanged(ByVal s As Object, ByVal e As
System.ComponentModel.ListChangedEventArgs)

If b Then Return
b = True ' don't want recursive calling

dt.Rows.Add(New Object() {"c", "d"})

End Sub

End Module
 
U

Urs Eichmann

Angel,
I don't agree with this answer, for these reasons:

a) the event occurs on the *same* thread as the main program, so it is
*not* a multi-threading problem (you can see for yourself if you watch
it in the debugger). So using "Invoke" won't make any difference IMHO.

b) It is *not* documented anywhere that "write" operations in an
EventHandler are not supported (at least I couldn't find this in the docs)

c) This code ran fine *without* SP1, in fact even back with .NET 1.0
there was no problem.

d) I couldn't find any hint in the SP1 docs that there are
incompatiblities to be expected in the DataView class between RTM and SP1.

I modified the repro program so that the event doesn't add a new row,
but changes the one just added. This is quite a common scenario: Apply
calculated values into certain columns of a new row which the user just
entered. This worked with pre-SP1 releases, but no longer works now. I
think this is a serious thing which shouldn't be taken on the light
shoulder. At least there should be a KB article which explains a workaround.

-------- Start Repro -----

Imports System.Data

Module Module1

Private dt As DataTable
Private dv, dv2 As DataView

Sub Main()

dt = New System.Data.DataTable
dt.Columns.Add("Col1", GetType(String))
dt.Columns.Add("Col2", GetType(String))

dv = New DataView(dt, "", "Col1", DataViewRowState.CurrentRows)
AddHandler dv.ListChanged, AddressOf OnListchanged

' The program only fails if there is more than one View, so
create a second one
dv2 = New DataView(dt, "", "Col2", DataViewRowState.CurrentRows)

dt.Rows.Add(New Object() {"a", "b"}) ' NullReferenceExeption
occurs here

End Sub

Private Sub X()

End Sub

Private Sub OnListchanged(ByVal s As Object, ByVal e As
System.ComponentModel.ListChangedEventArgs)

Static recusive As Boolean
If recusive Then Return
recusive = True

' Modify the row which was just added
Dim r As DataRowView = dv.Item(e.NewIndex)
r.BeginEdit()
r("Col2") = "xxx"
r.EndEdit()

End Sub

End Module

---- End Repro ---------


Best regards,
Urs

Uris,
This is the response that I got from the dataset team:
"This is an unsupported scenario. Any "write" operations on DataSet in an
event handler will result in an unpredictable behavior.
I'd suggest an alternative way of solving his scenario."

I am not sure of what they mean with alternative solution, but it is true
that "touching" the datatable in multiple threads is not supported. You can
probably get arround this limitation by binding on the UI thread before
calling the Add method with something like this (please excuse the code
hack, I am doing copy paste from a c# project I had laying arround,
hopefully you can get the idea of what to look for from here). The basic
concept is that you can only call datatable add on the same thread in which
you created the datatable, in this case we assume you created it on the main
thread.


delegate void UICallback( object param );

void ReBindOnUIThread( object param )
{
//This method will run in the main thread, we can touch the DataTable
here:
dt.Rows.Add(New Object() {"c", "d"})
}

Private Sub OnListchanged(ByVal s As Object, ByVal e As
System.ComponentModel.ListChangedEventArgs)

If b Then Return
b = True ' don't want recursive calling
//you can't touch the datatable here since we are in a different
thread
//dt.Rows.Add(New Object() {"c", "d"})
//instead we rebind on the ui thread using the delegate
this.Invoke( new UICallback( ReBindOnUIThread ), new object[] {
<myobject>} );

End Sub
 
A

Angel Saenz-Badillos[MS]

Urs,
I have pointed Ravi from the dataset team to this thread, hopefully he will
be able to help.

--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging about ADO.NET: http://weblogs.asp.net/angelsb/




Urs Eichmann said:
Angel,
I don't agree with this answer, for these reasons:

a) the event occurs on the *same* thread as the main program, so it is
*not* a multi-threading problem (you can see for yourself if you watch
it in the debugger). So using "Invoke" won't make any difference IMHO.

b) It is *not* documented anywhere that "write" operations in an
EventHandler are not supported (at least I couldn't find this in the docs)

c) This code ran fine *without* SP1, in fact even back with .NET 1.0
there was no problem.

d) I couldn't find any hint in the SP1 docs that there are
incompatiblities to be expected in the DataView class between RTM and SP1.

I modified the repro program so that the event doesn't add a new row,
but changes the one just added. This is quite a common scenario: Apply
calculated values into certain columns of a new row which the user just
entered. This worked with pre-SP1 releases, but no longer works now. I
think this is a serious thing which shouldn't be taken on the light
shoulder. At least there should be a KB article which explains a workaround.

-------- Start Repro -----

Imports System.Data

Module Module1

Private dt As DataTable
Private dv, dv2 As DataView

Sub Main()

dt = New System.Data.DataTable
dt.Columns.Add("Col1", GetType(String))
dt.Columns.Add("Col2", GetType(String))

dv = New DataView(dt, "", "Col1", DataViewRowState.CurrentRows)
AddHandler dv.ListChanged, AddressOf OnListchanged

' The program only fails if there is more than one View, so
create a second one
dv2 = New DataView(dt, "", "Col2", DataViewRowState.CurrentRows)

dt.Rows.Add(New Object() {"a", "b"}) ' NullReferenceExeption
occurs here

End Sub

Private Sub X()

End Sub

Private Sub OnListchanged(ByVal s As Object, ByVal e As
System.ComponentModel.ListChangedEventArgs)

Static recusive As Boolean
If recusive Then Return
recusive = True

' Modify the row which was just added
Dim r As DataRowView = dv.Item(e.NewIndex)
r.BeginEdit()
r("Col2") = "xxx"
r.EndEdit()

End Sub

End Module

---- End Repro ---------


Best regards,
Urs

Uris,
This is the response that I got from the dataset team:
"This is an unsupported scenario. Any "write" operations on DataSet in an
event handler will result in an unpredictable behavior.
I'd suggest an alternative way of solving his scenario."

I am not sure of what they mean with alternative solution, but it is true
that "touching" the datatable in multiple threads is not supported. You can
probably get arround this limitation by binding on the UI thread before
calling the Add method with something like this (please excuse the code
hack, I am doing copy paste from a c# project I had laying arround,
hopefully you can get the idea of what to look for from here). The basic
concept is that you can only call datatable add on the same thread in which
you created the datatable, in this case we assume you created it on the main
thread.


delegate void UICallback( object param );

void ReBindOnUIThread( object param )
{
//This method will run in the main thread, we can touch the DataTable
here:
dt.Rows.Add(New Object() {"c", "d"})
}

Private Sub OnListchanged(ByVal s As Object, ByVal e As
System.ComponentModel.ListChangedEventArgs)

If b Then Return
b = True ' don't want recursive calling
//you can't touch the datatable here since we are in a different
thread
//dt.Rows.Add(New Object() {"c", "d"})
//instead we rebind on the ui thread using the delegate
this.Invoke( new UICallback( ReBindOnUIThread ), new object[] {
<myobject>} );

End Sub
 
G

Guest

Hi, didn't hear anything vom Ravi or anyone from MS regarding this issue.
We're currently blocked with our App...

Urs


Angel Saenz-Badillos said:
Urs,
I have pointed Ravi from the dataset team to this thread, hopefully he will
be able to help.

--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging about ADO.NET: http://weblogs.asp.net/angelsb/




Urs Eichmann said:
Angel,
I don't agree with this answer, for these reasons:

a) the event occurs on the *same* thread as the main program, so it is
*not* a multi-threading problem (you can see for yourself if you watch
it in the debugger). So using "Invoke" won't make any difference IMHO.

b) It is *not* documented anywhere that "write" operations in an
EventHandler are not supported (at least I couldn't find this in the docs)

c) This code ran fine *without* SP1, in fact even back with .NET 1.0
there was no problem.

d) I couldn't find any hint in the SP1 docs that there are
incompatiblities to be expected in the DataView class between RTM and SP1.

I modified the repro program so that the event doesn't add a new row,
but changes the one just added. This is quite a common scenario: Apply
calculated values into certain columns of a new row which the user just
entered. This worked with pre-SP1 releases, but no longer works now. I
think this is a serious thing which shouldn't be taken on the light
shoulder. At least there should be a KB article which explains a workaround.

-------- Start Repro -----

Imports System.Data

Module Module1

Private dt As DataTable
Private dv, dv2 As DataView

Sub Main()

dt = New System.Data.DataTable
dt.Columns.Add("Col1", GetType(String))
dt.Columns.Add("Col2", GetType(String))

dv = New DataView(dt, "", "Col1", DataViewRowState.CurrentRows)
AddHandler dv.ListChanged, AddressOf OnListchanged

' The program only fails if there is more than one View, so
create a second one
dv2 = New DataView(dt, "", "Col2", DataViewRowState.CurrentRows)

dt.Rows.Add(New Object() {"a", "b"}) ' NullReferenceExeption
occurs here

End Sub

Private Sub X()

End Sub

Private Sub OnListchanged(ByVal s As Object, ByVal e As
System.ComponentModel.ListChangedEventArgs)

Static recusive As Boolean
If recusive Then Return
recusive = True

' Modify the row which was just added
Dim r As DataRowView = dv.Item(e.NewIndex)
r.BeginEdit()
r("Col2") = "xxx"
r.EndEdit()

End Sub

End Module

---- End Repro ---------


Best regards,
Urs

Uris,
This is the response that I got from the dataset team:
"This is an unsupported scenario. Any "write" operations on DataSet in an
event handler will result in an unpredictable behavior.
I'd suggest an alternative way of solving his scenario."

I am not sure of what they mean with alternative solution, but it is true
that "touching" the datatable in multiple threads is not supported. You can
probably get arround this limitation by binding on the UI thread before
calling the Add method with something like this (please excuse the code
hack, I am doing copy paste from a c# project I had laying arround,
hopefully you can get the idea of what to look for from here). The basic
concept is that you can only call datatable add on the same thread in which
you created the datatable, in this case we assume you created it on the main
thread.


delegate void UICallback( object param );

void ReBindOnUIThread( object param )
{
//This method will run in the main thread, we can touch the DataTable
here:
dt.Rows.Add(New Object() {"c", "d"})
}

Private Sub OnListchanged(ByVal s As Object, ByVal e As
System.ComponentModel.ListChangedEventArgs)

If b Then Return
b = True ' don't want recursive calling
//you can't touch the datatable here since we are in a different
thread
//dt.Rows.Add(New Object() {"c", "d"})
//instead we rebind on the ui thread using the delegate
this.Invoke( new UICallback( ReBindOnUIThread ), new object[] {
<myobject>} );

End Sub
 
A

Angel Saenz-Badillos[MS]

Urs,
I have sent another email, hopefully he can contact you shortly.

Thanks,
--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging about ADO.NET: http://weblogs.asp.net/angelsb/




Urs Eichmann said:
Hi, didn't hear anything vom Ravi or anyone from MS regarding this issue.
We're currently blocked with our App...

Urs


Angel Saenz-Badillos said:
Urs,
I have pointed Ravi from the dataset team to this thread, hopefully he will
be able to help.

--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging about ADO.NET: http://weblogs.asp.net/angelsb/




Urs Eichmann said:
Angel,
I don't agree with this answer, for these reasons:

a) the event occurs on the *same* thread as the main program, so it is
*not* a multi-threading problem (you can see for yourself if you watch
it in the debugger). So using "Invoke" won't make any difference IMHO.

b) It is *not* documented anywhere that "write" operations in an
EventHandler are not supported (at least I couldn't find this in the docs)

c) This code ran fine *without* SP1, in fact even back with .NET 1.0
there was no problem.

d) I couldn't find any hint in the SP1 docs that there are
incompatiblities to be expected in the DataView class between RTM and SP1.

I modified the repro program so that the event doesn't add a new row,
but changes the one just added. This is quite a common scenario: Apply
calculated values into certain columns of a new row which the user just
entered. This worked with pre-SP1 releases, but no longer works now. I
think this is a serious thing which shouldn't be taken on the light
shoulder. At least there should be a KB article which explains a workaround.

-------- Start Repro -----

Imports System.Data

Module Module1

Private dt As DataTable
Private dv, dv2 As DataView

Sub Main()

dt = New System.Data.DataTable
dt.Columns.Add("Col1", GetType(String))
dt.Columns.Add("Col2", GetType(String))

dv = New DataView(dt, "", "Col1", DataViewRowState.CurrentRows)
AddHandler dv.ListChanged, AddressOf OnListchanged

' The program only fails if there is more than one View, so
create a second one
dv2 = New DataView(dt, "", "Col2", DataViewRowState.CurrentRows)

dt.Rows.Add(New Object() {"a", "b"}) ' NullReferenceExeption
occurs here

End Sub

Private Sub X()

End Sub

Private Sub OnListchanged(ByVal s As Object, ByVal e As
System.ComponentModel.ListChangedEventArgs)

Static recusive As Boolean
If recusive Then Return
recusive = True

' Modify the row which was just added
Dim r As DataRowView = dv.Item(e.NewIndex)
r.BeginEdit()
r("Col2") = "xxx"
r.EndEdit()

End Sub

End Module

---- End Repro ---------


Best regards,
Urs


Angel Saenz-Badillos[MS] wrote:
Uris,
This is the response that I got from the dataset team:
"This is an unsupported scenario. Any "write" operations on DataSet
in
an
event handler will result in an unpredictable behavior.
I'd suggest an alternative way of solving his scenario."

I am not sure of what they mean with alternative solution, but it is true
that "touching" the datatable in multiple threads is not supported.
You
can
probably get arround this limitation by binding on the UI thread before
calling the Add method with something like this (please excuse the code
hack, I am doing copy paste from a c# project I had laying arround,
hopefully you can get the idea of what to look for from here). The basic
concept is that you can only call datatable add on the same thread
in
which
you created the datatable, in this case we assume you created it on
the
main
thread.


delegate void UICallback( object param );

void ReBindOnUIThread( object param )
{
//This method will run in the main thread, we can touch the DataTable
here:
dt.Rows.Add(New Object() {"c", "d"})
}

Private Sub OnListchanged(ByVal s As Object, ByVal e As
System.ComponentModel.ListChangedEventArgs)

If b Then Return
b = True ' don't want recursive calling
//you can't touch the datatable here since we are in a different
thread
//dt.Rows.Add(New Object() {"c", "d"})
//instead we rebind on the ui thread using the delegate
this.Invoke( new UICallback( ReBindOnUIThread ), new
object[]
{
<myobject>} );

End Sub
 
G

Guest

Did anybody ever get a resolution to this problem? We are dealing with the
same problem.

Thanks

Angel Saenz-Badillos said:
Urs,
I have sent another email, hopefully he can contact you shortly.

Thanks,
--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging about ADO.NET: http://weblogs.asp.net/angelsb/




Urs Eichmann said:
Hi, didn't hear anything vom Ravi or anyone from MS regarding this issue.
We're currently blocked with our App...

Urs


Angel Saenz-Badillos said:
Urs,
I have pointed Ravi from the dataset team to this thread, hopefully he will
be able to help.

--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no
rights.Please do not send email directly to this alias.
This alias is for newsgroup purposes only.
I am now blogging about ADO.NET: http://weblogs.asp.net/angelsb/




Angel,
I don't agree with this answer, for these reasons:

a) the event occurs on the *same* thread as the main program, so it is
*not* a multi-threading problem (you can see for yourself if you watch
it in the debugger). So using "Invoke" won't make any difference IMHO.

b) It is *not* documented anywhere that "write" operations in an
EventHandler are not supported (at least I couldn't find this in the docs)

c) This code ran fine *without* SP1, in fact even back with .NET 1.0
there was no problem.

d) I couldn't find any hint in the SP1 docs that there are
incompatiblities to be expected in the DataView class between RTM and SP1.

I modified the repro program so that the event doesn't add a new row,
but changes the one just added. This is quite a common scenario: Apply
calculated values into certain columns of a new row which the user just
entered. This worked with pre-SP1 releases, but no longer works now. I
think this is a serious thing which shouldn't be taken on the light
shoulder. At least there should be a KB article which explains a
workaround.

-------- Start Repro -----

Imports System.Data

Module Module1

Private dt As DataTable
Private dv, dv2 As DataView

Sub Main()

dt = New System.Data.DataTable
dt.Columns.Add("Col1", GetType(String))
dt.Columns.Add("Col2", GetType(String))

dv = New DataView(dt, "", "Col1", DataViewRowState.CurrentRows)
AddHandler dv.ListChanged, AddressOf OnListchanged

' The program only fails if there is more than one View, so
create a second one
dv2 = New DataView(dt, "", "Col2", DataViewRowState.CurrentRows)

dt.Rows.Add(New Object() {"a", "b"}) ' NullReferenceExeption
occurs here

End Sub

Private Sub X()

End Sub

Private Sub OnListchanged(ByVal s As Object, ByVal e As
System.ComponentModel.ListChangedEventArgs)

Static recusive As Boolean
If recusive Then Return
recusive = True

' Modify the row which was just added
Dim r As DataRowView = dv.Item(e.NewIndex)
r.BeginEdit()
r("Col2") = "xxx"
r.EndEdit()

End Sub

End Module

---- End Repro ---------


Best regards,
Urs


Angel Saenz-Badillos[MS] wrote:
Uris,
This is the response that I got from the dataset team:
"This is an unsupported scenario. Any "write" operations on DataSet in
an
event handler will result in an unpredictable behavior.
I'd suggest an alternative way of solving his scenario."

I am not sure of what they mean with alternative solution, but it is
true
that "touching" the datatable in multiple threads is not supported. You
can
probably get arround this limitation by binding on the UI thread before
calling the Add method with something like this (please excuse the code
hack, I am doing copy paste from a c# project I had laying arround,
hopefully you can get the idea of what to look for from here). The basic
concept is that you can only call datatable add on the same thread in
which
you created the datatable, in this case we assume you created it on the
main
thread.


delegate void UICallback( object param );

void ReBindOnUIThread( object param )
{
//This method will run in the main thread, we can touch the
DataTable
here:
dt.Rows.Add(New Object() {"c", "d"})
}

Private Sub OnListchanged(ByVal s As Object, ByVal e As
System.ComponentModel.ListChangedEventArgs)

If b Then Return
b = True ' don't want recursive calling
//you can't touch the datatable here since we are in a
different
thread
//dt.Rows.Add(New Object() {"c", "d"})
//instead we rebind on the ui thread using the delegate
this.Invoke( new UICallback( ReBindOnUIThread ), new object[]
{
<myobject>} );

End Sub
 
G

Guest

Hi,
I am also having simliar problem with SP1, except I have datagrid bound to
dataset in runtime any changes made withing the datagrid throws a "Error when
committing row to the original data store" this occurs during rowupdating
event i think. anyway my program worked fine without SP 1 now its broken, and
not sure what to do to fix it. maybe i have made error in my code but somehow
dont think so because cannot debug as it seems to be within the datagrid or
dataset code. not sure. if anyone can help would be great.
thanks
 

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