Modifiying a dataview while enumeration it (1.x->2.0 broke)

G

Greg Burns

I have a DataView that is currently sorted by the Price column. The sort is
critical to the logic I am applying.

In .NET 1.x, it seems I was able to modify the Price column in my DataView
while enumerating it without any side effect. I know this is a bad idea,
but it was working. :)

It appears in .NET 2.0 this no longer works the same way. I had recompiled
my program in 2.0 and now my output changed. I've narrowed it down to this
bit of code. :(

Anyways, I need some help with rethinking how to do this.

dv.Sort = "Price DESC"
'dv.RowStateFilter = DataViewRowState.Unchange ' thinking this maybe the
key, modified rows will fall out of the enumeration perhaps

for each drv as datarowview in dv
' some logic
drv("Price") = something new value
next

I've considered cloning the underlying datatable and making a new dataview
so that the enumration won't be effected as I change the Price column. (I
do believe that is what is happening now, which I don't think happened
before). But if I am enumerating a copy of the dataview, then how to I
update my Price column back in the original table (all I have a reference to
is drv from the copy)? I hate to have to resort to some sort of Find
command, but it that is what it takes...

All suggestions welcome,
Greg
 
M

Miha Markic [MVP C#]

Hi Greg,

You can easily create another DataView on the same table and do updates
there.
 
G

Greg Burns

That seems like wise advice, but I not sure how to apply it.

Say I have two DataViews; dv1 & dv2. Both are the same filtered records from
original DataTable. Now I start enumerating over dv1. How do I change the
same row in dv2 without using some sort of Find command on dv2 based on
current datarowview in dv1?

Now that I think about it, not sure this will work either. As I modify the
Price column in dv2 won't it dynamically change the sort of dv1? Almost
seems like in .NET 1.x, that a dataview's sort order was static and now in
..NET 2.0 it can change as the underlying data changes. (I would have
thought it was always this way, but something's definately different since
my output changed after recompiling.)

I am beginning to think I need to have two Price columns. One I sort on
(who's value never changes), and one I update. Not very elegant.

Greg
 
G

Greg Burns

I threw together a small demo to see what the heck is going on:

Dim dt As New DataTable
dt.Columns.Add("price", GetType(System.Int32))

Dim dr As DataRow

dr = dt.NewRow
dr("price") = "1"
dt.Rows.Add(dr)

dr = dt.NewRow
dr("price") = "2"
dt.Rows.Add(dr)

dr = dt.NewRow
dr("price") = "3"
dt.Rows.Add(dr)

Dim dv As DataView = dt.DefaultView
dv.Sort = "price ASC"

For Each drv As DataRowView In dv
If drv("price") = 1 Then
drv("price") = 4
End If
Console.WriteLine("{0}", drv("price"))
Next

Console.ReadLine()

In .NET 1.1 the output is:

4
2
1

In .NET 2.0 the output changes to:

2
3
4

<sigh>


Greg Burns said:
That seems like wise advice, but I not sure how to apply it.

Say I have two DataViews; dv1 & dv2. Both are the same filtered records
from original DataTable. Now I start enumerating over dv1. How do I change
the same row in dv2 without using some sort of Find command on dv2 based
on current datarowview in dv1?

Now that I think about it, not sure this will work either. As I modify
the Price column in dv2 won't it dynamically change the sort of dv1?
Almost seems like in .NET 1.x, that a dataview's sort order was static and
now in .NET 2.0 it can change as the underlying data changes. (I would
have thought it was always this way, but something's definately different
since my output changed after recompiling.)

I am beginning to think I need to have two Price columns. One I sort on
(who's value never changes), and one I update. Not very elegant.

Greg
 
G

Greg Burns

Whoops! That should have said:

In .NET 1.1 the output is:

4
2
3

In .NET 2.0 the output changes to:

2
3
4

sorry for the confusion

Greg Burns said:
I threw together a small demo to see what the heck is going on:

Dim dt As New DataTable
dt.Columns.Add("price", GetType(System.Int32))

Dim dr As DataRow

dr = dt.NewRow
dr("price") = "1"
dt.Rows.Add(dr)

dr = dt.NewRow
dr("price") = "2"
dt.Rows.Add(dr)

dr = dt.NewRow
dr("price") = "3"
dt.Rows.Add(dr)

Dim dv As DataView = dt.DefaultView
dv.Sort = "price ASC"

For Each drv As DataRowView In dv
If drv("price") = 1 Then
drv("price") = 4
End If
Console.WriteLine("{0}", drv("price"))
Next

Console.ReadLine()

In .NET 1.1 the output is:

4
2
1

In .NET 2.0 the output changes to:

2
3
4

<sigh>
 
S

Steven Cheng[MSFT]

Hi Greg,

Thanks for your code snippet. Two things I'd like to confirm:

1. Since you define the column as Int32 type, we should use

drv("price") = 3 rather than drv("price") = "3"

2. For the .NET 2.0 DataView, when we specify a Sort expression for it and
then modify the DataView's certain DataRowView record's Sorted field, the
DataView collection will automatically resort the DataRowView collection so
as to make it still conform to the Sort expression. So even we use Index
(rather than foreach ) to access the DataRowView, it will automatically
resort it after any item (the sorted property) in it be changed. The
following test code could demonstrate on this:

=====================
Protected Sub WhileTest()
Dim dt As New DataTable
dt.Columns.Add("price", GetType(System.Int32))

Dim dr As DataRow

dr = dt.NewRow
dr("price") = 1
dt.Rows.Add(dr)

dr = dt.NewRow
dr("price") = 3
dt.Rows.Add(dr)

dr = dt.NewRow
dr("price") = 5
dt.Rows.Add(dr)

dr = dt.NewRow
dr("price") = 7
dt.Rows.Add(dr)

Dim dv As DataView = New DataView(dt)
dv.Sort = "price ASC"

Dim i As Integer = 0

While i < dv.Count

If dv(i)("price") = 1 Then
dv(i)("price") = 8
End If

Response.Write(String.Format("<br/>{0}", dv(i)("price")))
i = i + 1
End While

End Sub


Protected Sub DirectModifyTest()
Dim dt As New DataTable
dt.Columns.Add("price", GetType(System.Int32))

Dim dr As DataRow

dr = dt.NewRow
dr("price") = 1
dt.Rows.Add(dr)

dr = dt.NewRow
dr("price") = 3
dt.Rows.Add(dr)

dr = dt.NewRow
dr("price") = 5
dt.Rows.Add(dr)

dr = dt.NewRow
dr("price") = 7
dt.Rows.Add(dr)

Dim dv As DataView = New DataView(dt)
dv.Sort = "price ASC"


dv(2)("price") = 8

For Each drv As DataRowView In dv
Response.Write(String.Format("<br/>{0}", drv("price")))
Next

End Sub
End Class
===================================

So I think this is a new feature of the .NET 2.0.Also, if you are wanting a
static Row collection which won't be ReSort automatically, I'd suggest you
consider using the
DataTable.Select(filter as String, sort as String)

which will return a static DataRow[] array.

Thanks,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)


--------------------
| Reply-To: "Greg Burns" <greg_burns@DONT_SPAM_ME_hotmail.com>
| From: "Greg Burns" <[email protected]>
| References: <[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
| Subject: Re: Modifiying a dataview while enumeration it (1.x->2.0 broke)
| Date: Sun, 6 Nov 2005 08:46:50 -0500
| Lines: 102
| X-Priority: 3
| X-MSMail-Priority: Normal
| X-Newsreader: Microsoft Outlook Express 6.00.2900.2180
| X-RFC2646: Format=Flowed; Response
| X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2180
| Message-ID: <[email protected]>
| Newsgroups: microsoft.public.dotnet.framework.adonet
| NNTP-Posting-Host: pcp09349975pcs.harngt01.de.comcast.net 68.34.122.119
| Path: TK2MSFTNGXA01.phx.gbl!TK2MSFTNGP08.phx.gbl!TK2MSFTNGP12.phx.gbl
| Xref: TK2MSFTNGXA01.phx.gbl microsoft.public.dotnet.framework.adonet:38742
| X-Tomcat-NG: microsoft.public.dotnet.framework.adonet
|
| Whoops! That should have said:
|
| In .NET 1.1 the output is:
|
| 4
| 2
| 3
|
| In .NET 2.0 the output changes to:
|
| 2
| 3
| 4
|
| sorry for the confusion
|
| | >I threw together a small demo to see what the heck is going on:
| >
| > Dim dt As New DataTable
| > dt.Columns.Add("price", GetType(System.Int32))
| >
| > Dim dr As DataRow
| >
| > dr = dt.NewRow
| > dr("price") = "1"
| > dt.Rows.Add(dr)
| >
| > dr = dt.NewRow
| > dr("price") = "2"
| > dt.Rows.Add(dr)
| >
| > dr = dt.NewRow
| > dr("price") = "3"
| > dt.Rows.Add(dr)
| >
| > Dim dv As DataView = dt.DefaultView
| > dv.Sort = "price ASC"
| >
| > For Each drv As DataRowView In dv
| > If drv("price") = 1 Then
| > drv("price") = 4
| > End If
| > Console.WriteLine("{0}", drv("price"))
| > Next
| >
| > Console.ReadLine()
| >
| > In .NET 1.1 the output is:
| >
| > 4
| > 2
| > 1
| >
| > In .NET 2.0 the output changes to:
| >
| > 2
| > 3
| > 4
| >
| > <sigh>
| >
| >
| > | >> That seems like wise advice, but I not sure how to apply it.
| >>
| >> Say I have two DataViews; dv1 & dv2. Both are the same filtered
records
| >> from original DataTable. Now I start enumerating over dv1. How do I
| >> change the same row in dv2 without using some sort of Find command on
dv2
| >> based on current datarowview in dv1?
| >>
| >> Now that I think about it, not sure this will work either. As I
modify
| >> the Price column in dv2 won't it dynamically change the sort of dv1?
| >> Almost seems like in .NET 1.x, that a dataview's sort order was static
| >> and now in .NET 2.0 it can change as the underlying data changes. (I
| >> would have thought it was always this way, but something's definately
| >> different since my output changed after recompiling.)
| >>
| >> I am beginning to think I need to have two Price columns. One I sort
on
| >> (who's value never changes), and one I update. Not very elegant.
| >>
| >> Greg
| >>
| >> "Miha Markic [MVP C#]" <miha at rthand com> wrote in message
| >> | >>> Hi Greg,
| >>>
| >>> You can easily create another DataView on the same table and do
updates
| >>> there.
| >>>
| >>> --
| >>> Miha Markic [MVP C#]
| >>> RightHand .NET consulting & development www.rthand.com
| >>> Blog: http://cs.rthand.com/blogs/blog_with_righthand/
| >>
| >>
| >
| >
|
|
|
 
G

Greg Burns

Thansk for taking a look.

Unfortunately my real project is getting its DataView from a CreateChildRow
statement. So I am kinda stuck with what I got.

I'll tackle this problem in another way. I just wanted to bring this change
to light in case somebody else runs into it themselves.

Greg
 
Q

QuenHo

Greg,

I got the same problem in 1.x. Sometimes it works, sometimes it
doesn't. I don't thing its 1.x related, but maybe the cleaned the code
up. It's also terribly slow on largers dataviews. I used by mistake not
by design. Yes you have to change your program logic, but in the long
run, I think it's better.

QuenHo

Greg said:
Thansk for taking a look.

Unfortunately my real project is getting its DataView from a CreateChildRow
statement. So I am kinda stuck with what I got.

I'll tackle this problem in another way. I just wanted to bring this change
to light in case somebody else runs into it themselves.

Greg


Steven Cheng said:
So I think this is a new feature of the .NET 2.0.Also, if you are wanting
a
static Row collection which won't be ReSort automatically, I'd suggest you
consider using the
DataTable.Select(filter as String, sort as String)

which will return a static DataRow[] array.
 

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