HasChanges Question

  • Thread starter Thread starter Matthew
  • Start date Start date
M

Matthew

It seems that the haschanges property is set to true
whenever i change the position in the dataset. why does
moving to the next record cause the haschanges to be = to
true?

i want to be able to tell if the record has changed before
the user moves to the next record.
 
It shouldn't be unless something is changing. Let's say that you have 5
rows total all of which have values...if you move from 1 to 2 it's showing
changes? If you moved to a new row that could cause it but within the
exisitng dataset that sounds weird.

Can you post the code snippet that you are using to 'move' through the rows?
 
Yes, its very weird. i cannot figure it out.

if i fill the dataset. then check for haschanges. it
says no changes. but as soon as i setup my label with
the "reading record number # of count" and then check
again. it says there are changes. i dont know why this
is. it seems anytime i use the following code or similiar
code i get a haschanges = true.

dataset.bindingcontext(datasetname,datamember).position =+1

that is the code i believe i use, im not in front of it
now, but that causes the dataset to register a change.
whats really odd.. is that the haschanges
(rowchanges.modified) = true and the haschanges
(rowchanges.unchanged) = true at the same time.. explain
that.

HELP!!!!
 
It seems that the haschanges property is set to true
whenever i change the position in the dataset. why does
moving to the next record cause the haschanges to be = to
true?

i want to be able to tell if the record has changed before
the user moves to the next record.

I assume you are talking about DataTable.HasChanges ?

There is no concept of a "current position" (cursor) in ADO.NET. There
is no cursor as there was in ADO. There is also no such thing as a
"record", instead it is a "row" (DataRow class).

The only way I know to "move" through a DataTable is with a loop...

for (int i=0; i < dt.Count; i++)
{
DataRow dr = dt;
//use edit dr as required.
}

looping through the rows of a DataTable in no way changes the individual
rows.

--
Michael Lang, MCSD
See my .NET open source projects
http://sourceforge.net/projects/colcodegen (simple code generator)
http://sourceforge.net/projects/dbobjecter (database app code generator)
http://sourceforge.net/projects/genadonet ("generic" ADO.NET)
 
Yes, its very weird. i cannot figure it out.

if i fill the dataset. then check for haschanges. it
says no changes. but as soon as i setup my label with
the "reading record number # of count" and then check
again. it says there are changes. i dont know why this
is. it seems anytime i use the following code or similiar
code i get a haschanges = true.

dataset.bindingcontext(datasetname,datamember).position =+1

that is the code i believe i use, im not in front of it
now, but that causes the dataset to register a change.
whats really odd.. is that the haschanges
(rowchanges.modified) = true and the haschanges
(rowchanges.unchanged) = true at the same time.. explain
that.

HELP!!!!

HasChanges is on a DataSet, not on DataRow. So yes, a DataSet can
contain both changed and unchaged records! The actual usage of the
method is as follows:

bool DataSet.HasChanges(DataRowState state)

You pass in the state you want to check for, and it tells you if any of
the records have that state. Remember, there is no "current" row (no
such thing as a cursor as in ADO).

If you want the RowState of a single row, then query the RowState of that
DataRow.

There is no BindingContext property on the DataSet. BindingContext is on
the Control class. If you still need help, let us know what your actual
code is once you get a chance to look at it.

--
Michael Lang, MCSD
See my .NET open source projects
http://sourceforge.net/projects/colcodegen (simple code generator)
http://sourceforge.net/projects/dbobjecter (database app code generator)
http://sourceforge.net/projects/genadonet ("generic" ADO.NET)
 
Yes, i know there is no record, but a row is still a
record. tables have records. but im familiar with some
of the lingo.. anyway. there is no reference to a set
position, however there is a position method..(i believe)
that allows you to navigate. maybe im in the wrong forum??

ADO.NET uses dataadapters and datasets. (i thought) im
using oledbdatasets and adapters. Datasets have
a .position method. that is how you navigate. that is how
the data form wizard code is generated. thats what i
copied for my form that im having issues with.

all i can say is the only code i have in the program is
the navigation code. and as soon as i navigate to another
row, the haschanged.modified = true. i cant understand
this.

i use the dataadpter.fill(dataset, datamember) 'to fill
the dataset.

then i use a position command to set the current dataset
row to 0.

this is where the haschanged becomes true.


-----Original Message-----
It seems that the haschanges property is set to true
whenever i change the position in the dataset. why does
moving to the next record cause the haschanges to be = to
true?

i want to be able to tell if the record has changed before
the user moves to the next record.

I assume you are talking about DataTable.HasChanges ?

There is no concept of a "current position" (cursor) in ADO.NET. There
is no cursor as there was in ADO. There is also no such thing as a
"record", instead it is a "row" (DataRow class).

The only way I know to "move" through a DataTable is with a loop...

for (int i=0; i < dt.Count; i++)
{
DataRow dr = dt;
//use edit dr as required.
}

looping through the rows of a DataTable in no way changes the individual
rows.

--
Michael Lang, MCSD
See my .NET open source projects
http://sourceforge.net/projects/colcodegen (simple code generator)
http://sourceforge.net/projects/dbobjecter (database app code generator)
http://sourceforge.net/projects/genadonet ("generic" ADO.NET)

.
 
Yes, i know there is no record, but a row is still a
record. tables have records. but im familiar with some
of the lingo.. anyway. there is no reference to a set
position, however there is a position method..(i believe)
that allows you to navigate. maybe im in the wrong forum??

ADO.NET uses dataadapters and datasets. (i thought) im
using oledbdatasets and adapters. Datasets have
a .position method. that is how you navigate. that is how
the data form wizard code is generated. thats what i
copied for my form that im having issues with.

all i can say is the only code i have in the program is
the navigation code. and as soon as i navigate to another
row, the haschanged.modified = true. i cant understand
this.

i use the dataadpter.fill(dataset, datamember) 'to fill
the dataset.

then i use a position command to set the current dataset
row to 0.

this is where the haschanged becomes true.

There is no "HasChanged.Modified" to check. You must mean:

DataSet.HasChanges(DataRowState.Modified) is returning true.

All that means is that at least one record has changed in the DataSet,
not the "Current" row. As I have said already, THERE IS NO CURRENT ROW.
Stop assuming that HasChanges() is limited to the state of a (non-
existant) "current" row.

There is no Position property on a DataSet or DataTable or DataAdapter.
Take a look at the help files.

However, BindingManagerBase does have a Position property.
CurrencyManager derives from BindingManagerBase, and thus also has a
Position property. Nothing else in the System.Data namespace has a
Position property (according to the help files index).

The Position property returns an integer, not a DataRow. But you can use
that Position to get the DataRow with that index in the DataRowCollection
of your DataTable (Rows property). Once you have a reference to that
DataRow, then query it's RowState property.

There is no "OleDbDataSet" Each provider has the following classes:
"PrvConnection", "PrvCommand", "PrvParameter", "PrvDataAdapter",
"PrvTransaction", and "PrvParameterCollection".

DataSet, DataTable, DataRow, DataRowState are all database provider
independant classes / enums.

Here is how to use the CurrencyManager to get the current DataRow
selected in a DataGrid:
============================================================
given:
"DataGrid dgCustomers;" on the form

CurrencyManager cm;
cm = (CurrencyManager)dgCustomers.BindingContext[
dgCustomers.DataSource, dgCustomers.DataMember];

//get the DataRow referenced by the current row in the grid:
DataRow dr = ((DataRowView)cm.Current).Row;
============================================================

Hope this helps.

Please read the help files I have mentioned, and try my suggestion before
you respond with more untrue statements.

--
Michael Lang, MCSD
See my .NET open source projects
http://sourceforge.net/projects/colcodegen (simple code generator)
http://sourceforge.net/projects/dbobjecter (database app code generator)
http://sourceforge.net/projects/genadonet ("generic" ADO.NET)
 
There is no "HasChanged.Modified" to check. You must
mean:


As i mentioned.. im not in front of my code. so i cant
give you the exact syntax. but you are correct, the code
below is what im using to check status of the "DATASET"
not the row. forgive me im a newbie.

There is no Position property on a DataSet or DataTable or DataAdapter.
Take a look at the help files.

Once Again, not infront of code, and i dont have the
studio.net class structure memorized yet. so again you
are correct, i use the following line which i thought was
correct. "DataSet.Bindingcontext(DataSetname,
Datamember).position =+1" to change records. if im not
mistaken. thats the exact code a vB.net form wizard uses
to Navigate (if we still do that now) a dataset.

i dont know what you mean by there is no OLEDBDataset.

in my studio.net VB project on the left side. under data i
see a list of objects, which im using called (i believe)

OLEDBDataApter
OLEDBDataSet
OLEDBConnection

i use a connection to link to the database, an adapter to
fill the dataset, and update the tables. I use the
methods and properties (if that is correct) to do my
business with the records or whatever you call them now.
just like microsoft to take the database out of database.
and the basic out of visual basic.

sorry if im a bit confused, but this is nothing like VB6
and i cant understand why properties and methods dont
describe what they really should. i mean position, to me,
means virtual position in the dataset. i mean why else
would the row change, if you update the position +1?
i dont know.. just curious as to why when i invoke a
position change and then check the dataset to see if there
are changes, (modifications) it says yes.
 
sorry if im a bit confused, but this is nothing like VB6
and i cant understand why properties and methods dont
describe what they really should.

Yes, I understand. It is VERY different. So different in fact, that all
the guesses you are making as to the meaning of a methods are wrong. What
you need to understand is that this is a totally different paradigm of data
access. Don't bring any preconceptions from ADO into your learning of
ADO.NET.

Go pick up a book on ADO.NET.

Your statement "why properties and methods don't describe what they really
should" is really just your opinion, not fact. I used ADO for over 2 years
before I switched to .NET. I think that ADO.NET is vastly superior to ADO.
I think all the method names and properties make perfect sense, and think
they describe exactly what they do. Of coarse this is my opionion, not
fact. I would assume it is also the opinion of Microsoft otherwise they
wouldn't have made those changes.

I've already answered how to solve your problem in the last post, I won't
respond further on that until you actually try my recommendation.
 
Micheal i appreciate your patience. i have been reading
the help files alot, however i dont always put 2 and 2
together. hands on is best for me. anyways here is a
pasted procedure i wrote. i plan on calling it from any
form i have open. i thought it would simplify data
navigation. the problem you will notice, is that when you
first click next. the dataset says no changes, before the
position change takes place. after the position change a
procedure is called to check for changes. you will see it
now thinks that there are changes. please tell me if my
code is even remotely correct.

Module RecordNavigation


Public Sub NavigateDataSet(ByRef FormName As Form,
ByVal DataSetName As DataSet, ByVal DataMember As String,
ByVal DataAdapter As OleDb.OleDbDataAdapter, ByVal Command
As String, ByVal RecordStatusControl As Control)
'Declaring needed variables
Dim RecordCount As Int64
Dim X As Integer
'
'Formname represents name of form object passed
'Datasetname is the name of the dataset object
passed
'Datamember is the name of the actual table you
are referring to in the dataset object.
'Dataadapter is the name of the
OleDb.OleDbDataAdapter being used to manage the given
dataset.
'RecordStatusControl is the name of the control
that is keeping track of the record status on the form

RecordCount = FormName.BindingContext(DataSetName,
DataMember).Count
' the select command below is used to determine
which button on the active form was pressed.
Select Case Command

Case "Next Record"
MsgBox(DataSetName.HasChanges
(DataRowState.Modified))
FormName.BindingContext(DataSetName,
DataMember).Position += 1
Call CheckForChanges(FormName,
DataSetName, DataMember, DataAdapter)


Case "Previous Record"
FormName.BindingContext(DataSetName,
DataMember).Position -= 1
Call CheckForChanges(FormName,
DataSetName, DataMember, DataAdapter)

Case "Last Record"
FormName.BindingContext(DataSetName,
DataMember).Position = RecordCount
Call CheckForChanges(FormName,
DataSetName, DataMember, DataAdapter)

Case "First Record"
FormName.BindingContext(DataSetName,
DataMember).Position = 0
Call CheckForChanges(FormName,
DataSetName, DataMember, DataAdapter)

Case "Add Record"
Call CheckForChanges(FormName,
DataSetName, DataMember, DataAdapter)
FormName.BindingContext(DataSetName,
DataMember).AddNew()


Case "Delete Record"
FormName.BindingContext(DataSetName,
DataMember).RemoveAt(FormName.BindingContext(DataSetName,
DataMember).Position)
DataAdapter.Update(DataSetName)
DataSetName.AcceptChanges()
'DataSetName.Tables(DataMember).Rows
(FormName.BindingContext(DataSetName,
DataMember).Position).Delete()

Case "Save Record"
FormName.BindingContext(DataSetName,
DataMember).EndCurrentEdit()
DataAdapter.Update(DataSetName)
DataSetName.AcceptChanges()

End Select

'this code is used to update the actual
RecordStatusLabel on the open form.
'you have to get the indexof the control, since
you cant seem to reference a control that does not yet
exist in the forms collection

X = FormName.Controls.IndexOf(RecordStatusControl)
FormName.Controls(X).Text = "Currently Viewing
Record # " & FormName.BindingContext(DataSetName,
DataMember).Position + 1 & " of " & FormName.BindingContext
(DataSetName, DataMember).Count

End Sub

Public Sub CheckForChanges(ByVal FormName As Form,
ByVal DataSetName As DataSet, ByVal DataMember As String,
ByVal DataAdapter As OleDb.OleDbDataAdapter)
'declaring variables
Dim ReturnInt As Integer
Dim KeyString As String

'checking to see if we should prompt for save
KeyString = GetSetting
("GigBooks", "General", "NoSavePrompt", KeyString)

'checking to see if dataset has changed, if it has
then we need to update the database.
MsgBox(DataSetName.HasChanges
(DataRowState.Modified))

If KeyString = "Yes" Then
FormName.BindingContext(DataSetName,
DataMember).EndCurrentEdit()
DataAdapter.Update(DataSetName) 'updating the
database
DataSetName.AcceptChanges() 'forcing the
dataset to match the database
Else
ReturnInt = MsgBox("The previous record has
changed. Would you like to save your changes?",
MsgBoxStyle.YesNo, "Save Changes")
If ReturnInt = 6 Then
FormName.BindingContext(DataSetName,
DataMember).EndCurrentEdit()
DataAdapter.Update(DataSetName,
DataMember) 'updating the database
DataSetName.AcceptChanges() 'forcing the
dataset to match the database
Else
DataSetName.RejectChanges() 'undoes all
the changes made to the dataset, in all table rows. (we
work in 1 at a time)
End If
End If


End Sub

End Module
 
I wonder if it has anything to do with the fact that my
forms do not have all the text boxes bound to a column?
im only using a few text boxes to check this module.

other than that, im not making any changes to the dataset,
just clicking next, next , previous. etc.
 
Micheal i appreciate your patience. i have been reading
the help files alot, however i dont always put 2 and 2
together. hands on is best for me. anyways here is a
pasted procedure i wrote. i plan on calling it from any
form i have open. i thought it would simplify data
navigation. the problem you will notice, is that when you
first click next. the dataset says no changes, before the
position change takes place. after the position change a
procedure is called to check for changes. you will see it
now thinks that there are changes. please tell me if my
code is even remotely correct.
Case "Next Record"
MsgBox(DataSetName.HasChanges
(DataRowState.Modified))
FormName.BindingContext(DataSetName,
DataMember).Position += 1
Call CheckForChanges(FormName,
DataSetName, DataMember, DataAdapter)


I've said this over and over again...

DataSetName.HasChanges(DataRowState.Modified)

This will tell you if ANY records in the entire DataSet have the Modified
RowState! There is no cursor, and thus no current record.

I think you need to buy a book. I don't think I can explain this to you
any better than I already have.

I recommend Arlen Feldman's book "ADO.NET Programming" ISBN 1-930110-29-4
 
Micheal,

I KNOW IT ONLY CHECKS FOR CHANGES IN THE DATASET!!!. but
what your not getting is that im not trying to check the
current record for changes. i dont need to. Since the
user only navigates one row at a time, i only care if the
dataset has changed. that will tell me if they just
changed that row. the problem is, it states there is a
change anytime a position value changes. even if no data
was modified in the bound controls. im not an idiot.

ive tested this on a microsoft created control, and it to
tells me that there are changes to the dataset after a
position change is made and no data was changed
physically.

Why don't you just check the row that the user just left for changes
instead? That is what you are prompting the user if they want to save
changes for, isn't it?

Have you used the locals window while debugging to see which record has
RowState = Modified? Which record is it that has the changes. Verify if
it is even the last record the user was looking at was really the changed
record. And have you found the line of code that causes that row to be
set as modified?

--
Michael Lang, MCSD
See my .NET open source projects
http://sourceforge.net/projects/colcodegen (simple code generator)
http://sourceforge.net/projects/dbobjecter (database app code generator)
http://sourceforge.net/projects/genadonet ("generic" ADO.NET)
 
Why don't you just check the row that the user just left
for changes
instead? That is what you are prompting the user if they want to save
changes for, isn't it?

i havent figured out the code to do that yet :(

Have you used the locals window while debugging to see which record has
RowState = Modified? Which record is it that has the changes. Verify if
it is even the last record the user was looking at was really the changed
record. And have you found the line of code that causes that row to be
set as modified?

Nope. i will surely try that. I havent messed around
with the locals window very much yet. i am new to
studio.net so i havent learned my way around the all the
features yet.

but, if i step thru the code, i realize the following.

i call the form - loads fine
fill the dataset- fills fine
i then check the rowstate - says no changes
i then set the current position to 0
i then chekc the rowstate - changes have occured.

thats whats boggling my mind. i will check the locals and
see what i can learn from that.
 
i havent figured out the code to do that yet :(


Maybe you missed this snippet? This is exactly how to get a reference to
a specific DataRow.
============================================================
given:
"DataGrid dgCustomers;" on the form

CurrencyManager cm;
cm = (CurrencyManager)dgCustomers.BindingContext[
dgCustomers.DataSource, dgCustomers.DataMember];

//get the DataRow referenced by the current row in the grid:
DataRow dr = ((DataRowView)cm.Current).Row;
============================================================

You were already using the BindingContext of the form:

RecordCount = FormName.BindingContext(DataSetName,
DataMember).Count

Cast that to a CurrenyManager as in my example snippet...

CurrencyManager cm = (CurrencyManager)FormName.BindingContext
(DataSetName, DataMember)

then get the row...

DataRow dr = ((DataRowView)cm.Current).Row;

now you can check that rows RowState...

if (dr.RowState == DataRowState.Modified)
{ ... handle row change... }

--
Michael Lang, MCSD
See my .NET open source projects
http://sourceforge.net/projects/colcodegen (simple code generator)
http://sourceforge.net/projects/dbobjecter (database app code generator)
http://sourceforge.net/projects/genadonet ("generic" ADO.NET)
 
Back
Top