update DataRowView

Richnl

Well-known member
Joined
Mar 20, 2007
Messages
93
Programming Experience
Beginner
I still have some update issues
Now, I have a filtered dataview on wich I want to change some off the rows columns(field) values

clearly, I am not finished here because nothing got updated
I work with the dataset on the mainform that I want to update-
see:FTDBase.TDataSet.Jobs.DefaultView

I think, I need to find the primary key for each datarowview in the apointed tableadapter
on the mainform and change that row.

Is this the easiest way to do it?

VB.NET:
      Dim dv As DataView = FTDBase.TDataSet.Jobs.DefaultView
        Dim drv As DataRowView
        dv.RowFilter = Filter1
        i = dv.Count
        ' test(i.ToString)
        Dim CreditsFiltered As Decimal

        Dim dvIsFilteredCounter As IEnumerator = dv.GetEnumerator
        While dvIsFilteredCounter .MoveNext
            drv = dvIsFilteredCounter .Current
            CreditsFiltered = CreditsFiltered + drv("Credits")
            b = UpdateDataRowView(drv)
        End While
        Me.TotalTextBox.Text = Format(CreditsFiltered , "c2")
    
    End Sub

    Sub test(ByVal input As String)
        MsgBox(input, , "FieldData")
    End Sub


    Function UpdateDataRowView(ByVal drv As DataRowView) As Boolean
        drv.BeginEdit()
        test(drv("Column1").ToString)
        drv("Column1") = 1
               drv.EndEdit()
        ' test(drv("Column1").ToString)
               Return True
    End Function

thanks in adv, Richard
 
Last edited:
I still have some update issues
Now, I have a filtered dataview on wich I want to change some off the rows columns(field) values
Did you not go the .NET 2 route of using the BindingSource to filter?

clearly, I am not finished here because nothing got updated
I work with the dataset on the mainform that I want to update-
see:FTDBase.TDataSet.Jobs.DefaultView
Well, a view is nothing special, just an indirect connection to the row concerned

I think, I need to find the primary key for each datarowview in the apointed tableadapter
on the mainform and change that row.
You dont find data in tableadapters. TableAdapters are like to this what tractors are to farms; they push data around and put it between the field and the barn. They dont store hay themselves

Is this the easiest way to do it?
I'm not quite clear on what youre doing but I would hazard a guess at "no"

VB.NET:
      Dim dv As DataView = FTDBase.TDataSet.Jobs.DefaultView
        Dim drv As DataRowView
        dv.RowFilter = Filter1
        i = dv.Count
        ' test(i.ToString)
        Dim CreditsFiltered As Decimal

        Dim dvIsFilteredCounter As IEnumerator = dv.GetEnumerator
        While dvIsFilteredCounter .MoveNext
            drv = dvIsFilteredCounter .Current
            CreditsFiltered = CreditsFiltered + drv("Credits")
            b = UpdateDataRowView(drv)
        End While
        Me.TotalTextBox.Text = Format(CreditsFiltered , "c2")
    
    End Sub

    Sub test(ByVal input As String)
        MsgBox(input, , "FieldData")
    End Sub


    Function UpdateDataRowView(ByVal drv As DataRowView) As Boolean
        drv.BeginEdit()
        test(drv("Column1").ToString)
        drv("Column1") = 1
               drv.EndEdit()
        ' test(drv("Column1").ToString)
               Return True
    End Function

thanks in adv, Richard

If youre after getting an access to a subset of information froma datatable, so you can modify just those rows and then save the table, then you should just use dataTable.Select(), it returns an array of rows in the table that meet the criteria. Modiufy the values and they become Moified in state and will be persisted back. You can enumerate them as with any array
 
If youre after getting an access to a subset of information froma datatable, so you can modify just those rows and then save the table, then you should just use dataTable.Select(),...
Thanks, that worked better, except, - I have read the DNU link -, the database still holds the values when I restart because
copy if newer is active! That's ok, but when I make a connection in the server explorer, it will go back to the values before editing

I guess, I have to look at this behaviour that the IDE considers doing something in the server explorer as doing something to the structure off the database and thus copies the original "clean one" over the edited "dirty one" when the APP get's rebuild by pressing play.
I made the assumption that the edited values also would appear in the server explorer ->rightclick showtabledata
If this is right then things are working correctly, but you can correct me when I'm wrong


VB.NET:
Private Sub Test_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles knpNogEenTest.Click
        Dim i As Integer
        Dim ii As Integer
        Dim Filter1 As String
        Filter1 = String.Format( _
        "theDate>= #{0:M/dd/yyyy}# AND theDate<= #{1:M/dd/yyyy}#", dtp1.Value, dtp2.Value) _
        & " AND LedenID =" & Me.cboLedenID.SelectedItem(0) & " AND IsPaid =0"
        Dim nFilterRijen() As DataRow = FTDBase.TDataSet.Jobs.Select(Filter1)
        ii = nFilteredRows.Length
        For ii = 0 To nFilteredRows.Length - 1
            test(nFilteredRows(ii)("theDate").ToString)
            UpdateDataRowView(nFilterRijen(ii))
            '  nFilteredRows(ii)("IsPaid") = 1
        Next
        Me.TestTextBox.Text = ii.ToString
    End Sub

    Function UpdateDataRowView(ByVal dr As DataRow) As Boolean
        dr.BeginEdit()
        test(dr("IsPaid").ToString)
        dr("IsPaid") = 1
                 dr.EndEdit()
        test(dr("IsPaid").ToString)
        FTDBase.daJobs.Update(FTDBase.TDataSet.Jobs)
        'FTDBase.daJobs.Fill(FTDBase.TDataSet.Jobs)
        Return True
    End Function
 
Last edited:
Thanks, that worked better, except, - I have read the DNU link -, the database still holds the values when I restart because
copy if newer is active! That's ok, but when I make a connection in the server explorer, it will go back to the values before editing

Of course. Here's why:

You have a Clean database. It contains ONE table with ONE value:
Table1.Field1 = "Hello World"

This database was created on 01 jan 2007

You write an app that edits this value, and set copy if newer

You press play.

The clean database is copied to the debug folder

The debug database has todays date, 25 may 2007 12 pm

The debug database is edited, it now says "Goodbye World"

Here is how things are:
CleanDB\Table1.Field1 = "Hello World" - 01 jan 2007
DebugDB\Table1.Field1 = "Goodbye World" - 25 may 2007

Press play again. Copy if Newer? is 01 jan 2007 newer than 25 may 2007? NO. The database is NOT copied

Now go back to the server explorer and edit your clean database, add another column:

CleanDB\Table1.Field2 = "Good Morning Vietnam"

Now your clean database as JUST BEEN MODIFIED. It has date 25 may 2007 3pm

Now press play

Is CleanDB newer than DebugDB? Is 25 may 2007 3pm newer than 25 may 2007 12pm? YES. Databse is copied out

DebugDB that said "Goodbye World" is now replaced with a Clean DB that is "Hello World"/"Good Morning Vietnam"


Isnt it so easy, and obvious when you think about it?


Put it simple: It should be this way. You shouldnt release a "dirty" database with all your test values in. If you need them really truly to be in the release, then PUT THEM IN THE CLEAN DB. If that means copying the debug db back to the clean folder then do that MANUALLY whenever needed



VB.NET:
Private Sub Test_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles knpNogEenTest.Click
        Dim i As Integer
        Dim ii As Integer
        Dim Filter1 As String
        Filter1 = String.Format( _
        "theDate>= #{0:M/dd/yyyy}# AND theDate<= #{1:M/dd/yyyy}#", dtp1.Value, dtp2.Value) _
        & " AND LedenID =" & Me.cboLedenID.SelectedItem(0) & " AND IsPaid =0"
Looks like we're still having trouble understanding string.format:

VB.NET:
BAD:
String.Format( _
        "theDate>= #{0:M/dd/yyyy}# AND theDate<= #{1:M/dd/yyyy}#", dtp1.Value, dtp2.Value) _
        & " AND LedenID =" & Me.cboLedenID.SelectedItem(0) & " AND IsPaid =0")

GOOD:
String.Format( _
  "theDate>= #{0:M/dd/yyyy}# AND theDate<= #{1:M/dd/yyyy}# AND LedenID = {2} AND IsPaid =0", _ 
  dtp1.Value, dtp2.Value, Me.cboLedenID.SelectedItem(0) _
)

Here's a simple rule. If you write some vb code that
a) uses more than one & sign in a single statement
b) uses an & sign in a loop

Then consider string.Format and stringbuilder respectively

If you say that "but I have a very long string that extends over 3 lines and I need 3 & signs" then you should be putting that string in the settings. Actually, you should be putting all strings in the settings. It makes the program MUCH easier to translate to another language


VB.NET:
        Dim nFilterRijen() As DataRow = FTDBase.TDataSet.Jobs.Select(Filter1)
        ii = nFilteredRows.Length
        For ii = 0 To nFilteredRows.Length - 1
            test(nFilteredRows(ii)("theDate").ToString)
            UpdateDataRowView(nFilterRijen(ii))
            '  nFilteredRows(ii)("IsPaid") = 1
        Next
        Me.TestTextBox.Text = ii.ToString
    End Sub

    Function UpdateDataRowView(ByVal dr As DataRow) As Boolean
        dr.BeginEdit()
        test(dr("IsPaid").ToString)
        dr("IsPaid") = 1
                 dr.EndEdit()
        test(dr("IsPaid").ToString)
        FTDBase.daJobs.Update(FTDBase.TDataSet.Jobs)
        'FTDBase.daJobs.Fill(FTDBase.TDataSet.Jobs)
        Return True
    End Function


Also your function names need improving. Why do you call the function UpdateDataRowView when it updates a data row?

Also, why do you send the changes back to the database every time it is called?

Better:
VB.NET:
Dim nFilterRijen() As DataRow = FTDBase.TDataSet.Jobs.Select(Filter1)
Dim ro as TDataSet.JobsRow
For idx as Integer = 0 To nFilteredRows.Length - 1
  ro = DirectCast(nFilteredRows(idx), TDataSet.JobsRow)
  ro.IsPaid = 1
Next idx

FTDBase.daJobs.Update(FTDBase.TDataSet.Jobs)
 
Also, I'm wary of you saying cboXXX.SelectedItem(0)

I dont know if this is intentional, but if .SelectedItem returns a string, then .SelectedItem(0) gets you the first character of the string

Some controls have a .SelectedItems property, where .SelectedItems(0) would return the first item.

To me it looks like a typo(only because I suspect cboXXX to be a combobox and combos dont have SelectedItems), but it could be intentional. I dont know in this case. Just thought i'd mention that I noticed it. To be honest you would likely be best off NOT using the display values.

Combos have .DisplayMember and .ValueMember - for any given display member you can make the .ValueMember the thing you should search for

That way display can say "Apples - Golden Delicious" but value can be a code like "GOLD_DELI"
 
about the dirty and clean database
main thing is that I am not doing anything wrong....
thanks for the explanatory

Also, I'm wary of you saying cboXXX.SelectedItem(0) I dont know if this is intentional,......
It gives me the value 4 from the displayed value ""TH04"........which is the actual increment value
The combo gets populated by an expressioncolumn that did the prefix "TH0"
Me.cboXXX.DataSource = FTDBase.TDataSet.Jobs
Me.cboXXX.DisplayMember = "myID"

so, cboXXX.SelectedItem(0) gives me 4
but that's still dum luck then, because I don't surpass two characters with testing
what should I use instead then..?
another way that I at least know is by using -- Mid(Me.cboXXX.Text, 4)) --
[the number without the prefix from the combobox must become the value of another databound textbox]


Dim nFilterRijen() As DataRow = FTDBase.TDataSet.Jobs.Select(Filter1)
Dim ro as TDataSet.JobsRow
For idx as Integer = 0 To nFilteredRows.Length - 1
ro = DirectCast(nFilteredRows(idx), TDataSet.JobsRow)
ro.IsPaid = 1
Next idx

FTDBase.daJobs.Update(FTDBase.TDataSet.Jobs)

shouldn't it be
VB.NET:
Dim ro as [COLOR="Red"]FTDBase[/COLOR].TDataSet.JobsRow
ro = DirectCast(nFilteredRows(idx), [COLOR="Red"]FTDBase.[/COLOR]TDataSet.JobsRow)
No, can't be..I tested it
then I hope this works, because I thougt you had to use one instance for an update operation(or directcast is a type setting)
the error help also points out that the syntax can only be projectname.TDataset
so there is a generic name, and the separate instances you drag to a form are derived from that and can hold a subset of data
The type Tdataset(or main Tdataset) holds all the references to all the tables (see intellisense) whereas me.Tdataset(derived instance-partially filled) does not have too
It's leaving me a bit confused again...so directcast only tells it's a typeof jobsrow..I thought it already knew that, because I pulled them out of there


could you explain what Directcast actually does in logical terms...bit of a mystery to me
 
Last edited:
about the dirty and clean database
main thing is that I am not doing anything wrong....
thanks for the explanatory


It gives me the value 4 from the displayed value ""TH04"........which is the actual increment value
The combo gets populated by an expressioncolumn that did the prefix "TH0"
Me.cboXXX.DataSource = FTDBase.TDataSet.Jobs
Me.cboXXX.DisplayMember = "myDisplayText"
and also:
Me.cboXXX.ValueMember = "myID"


so, cboXXX.SelectedItem(0) gives me 4
but that's still dum luck then, because I don't surpass two characters with testing
You would use cboXXX.SelectedValue to retrieve the "myID" for whatever "myDisplayText" is on show





shouldn't it be
VB.NET:
Dim ro as [COLOR="Red"]FTDBase[/COLOR].TDataSet.JobsRow
ro = DirectCast(nFilteredRows(idx), [COLOR="Red"]FTDBase.[/COLOR]TDataSet.JobsRow)
No, because when we write:

Dim NAME as TYPE

It isnt anything to do with the form instance. So you have a dataset class called MyDataSet, and the instance of it on Form1 is called myDataSet1

You would say:

Dim ro as MyDataSet.MySomethingRow


You WOULD NOT say:

Dim ro as Form1.myDataSet1.MySomethingRow


Because the latter is not a TYPE, it is an instance.


otherwise the instance on the mainform doesn't receive updated rows, am I right

Youre actually more likely to mean:

Dim ro as MyDataSet.MySomethingRow = Form1.myDataSet1.Rows(0)


I have removed the cast for clarity. Hopefully you can see the difference between declaring a variable, and telling vb what the TYPE is (left hand side of =) and assigning that variable a value (right hand side of =)

also the datagridview on the mainform should display the changes
the instance off the dataset is on the mainform(FTDBase)
the rest are all edit forms derived from the data displayed on the mainform in datagridview or otherwise
You should consider calling your form FTDBaseForm. Other than that, yes you have it right. If you want other forms to edit this forms data then they do need to access the isntance of the dataset on this form

could you explain what Directcast actually does in logical terms...bit of a mystery to me

Consider this:

VB.NET:
Dim s as String = "Hello World"

Dim o as Object

o = s 'object is the super type of all things. This operation is called boxing

Now we have a string, but it is boxed up as an object

Consider a childs toy, at christmas. The toy is a rattle. It looks like a rattle. It rattles when you shake it

Now put the toy back in its box

Now the toy looks like a cardboard box.

IT IS STILL A RATTLE
IT RATTLES WHEN YOU SHAKE IT

Now wrap it in gift wrap paper

The toy looks like a shiny colourful cuboid

IT IS STILL A RATTLE
IT RATTLES WHEN YOU SHAKE IT

But it looks like a box.


DirectCast is for the opposite operation, the unwrapping


We can say:

VB.NET:
o = s

We cannot say:
VB.NET:
s = o

Without a cast. It s arule of inheritance in OO.. anything can be put into a parent box, but to put something into a child box, it must be cast. The cast only succeeds if the thing (the rattle) really is of the child type:

VB.NET:
s = DirectCast(o, String)

rattle = DirectCast(cardBoardBox, Rattle)
rattle = DirectCast(prettyColouredCuboid, Rattle)

In our inheritance tree of:

PrettyColouredCubiod / CardboardBox / Rattle
<--no--cast--needed-----
----must--cast--each--time--->



Generic parent super types can always contain their specific child subtypes
We get back to the specific child through casting
 
You would use cboXXX.SelectedValue to retrieve the "myID" for whatever "myDisplayText" is on show
That makes life much simpler!

The RATTLE analogy is good, thanks

Dim nFilterRijen() As DataRow = FTDBase.TDataSet.Jobs.Select(Filter1)
Dim ro as TDataSet.JobsRow
For idx as Integer = 0 To nFilteredRows.Length - 1
ro = DirectCast(nFilteredRows(idx), TDataSet.JobsRow)
ro.IsPaid = 1
Next idx

FTDBase.daJobs.Update(FTDBase.TDataSet.Jobs)
just this, it gives the error (Update requires a valid UpdateCommand when passed DataRow collection with modified rows.)
I see you also left out the beginedit/endedit (..maybe it's not nessasary?)
Am going to investigate that right now.
I will get back if I found the reason of the error myself.

Found it, primary key is required for the update command to find the modified rows
 
Last edited:
I see you also left out the beginedit/endedit (..maybe it's not nessasary?)

It's moot if you only alter one value on a row anyway

I never call BeginEdit
I only call EndEdit when working with visual controls to edit the data
 
Back
Top