I have a winforms application, that is using the datasource and dataset controls from the IDE
This is the code block i am using
dsParcelBatch.BC_cpo_PARCELRow pr = dsParcelBatch.BC_cpo_PARCEL.FindByISN(int.Parse(activeParcelID));
pr.BeginEdit();
pr.NODE_ISN = 6;
pr.EndEdit();
pr.AcceptChanges();
dsParcelBatch.AcceptChanges();
I can read the correct row in line 1, and it is populating the PR row with the correct values,
i call the beginedit, and the dsParcelBatch has not updated.
I change the value of the NODE_ISN to the new value, and it sticks
I close the edit, and accept the changes in the row.
I can look into the datasource (dsParcelBatch) and the changes are in there - YEA!
I call the dsParcelBatch, and the changed value is changed....
but when i view the database, the value is back to the original value (5)
What am i missing something?
Before calling AcceptChanges you need to use a DataAdapter to Update the database.
AcceptChanges only changes the state of the rows in the DataTable, not in the database.
MSDN:
When AcceptChanges is called, any DataRow object still in edit mode
successfully ends its edits. The DataRowState also changes: all Added
and Modified rows become Unchanged, and Deleted rows are removed.
Related
I have a group of data sets and they are all editable, what I need is a function that copies all of the information in the data tables and saves it back into the data set or as a seperate xml.
Ultimately, a DataTable is updatable. I can write
ds.Tables[0].Rows[0][0] = "Test"
(where ds is a DataSet) and that will update row 1, column 1 of the first DataTable within the DataSet. What I do from there with it is my choice, but the change is there in the in-memory copy of the DataSet.
If you're populating from a database via a DataAdapter, you can then call Update() to commit the changes back to the database, but if you're not in that scenario, then your change will remain in memory until you either dispose of the DataSet/s or go back off to the source to fetch them again.
I think the bottom line here is that you don't need a function to update DataTables, as they are inherently capable of being updated.
I have a DataGridView. It uses a BindingSource, a DataTable in a DataSet, and a TableAdapter to add/change/delete data in a table. It worked OK, but stopped working when I added a field/column, and I can't figure out what I did or how fix it.
The user can add a new row at the bottom of the DataGridView, but when he goes to save, the row disappears and is not saved. In addition, if he tries to type a second new row, the first new row disappears.
Existing Rows can be changed and saved back to the database successfully.
I've been asked for code. OK, here is code. (I've eliminated some error checking done by scanning dtDep) The point that after the third line is executed, there are no rows in dtDep even though a new row had been entered into the DataGridView. If a row had been retrieved, it would be in dtDep and the database table updated by the last statement.
this.Validate();
bsBelkDep.EndEdit();
DataTable dtDep = dsBelk.Tables["belk_elig_dep"];
int n = belk_elig_depTableAdapter.Update(this.dsBelk.belk_elig_dep);
It was a problem with the DataGridView, but I don't know what. I started deleting and re-creating the various object, and after the I recreated the DataGridView, it worked OK. Which was a pain because I have to do significant reformatting, but at least it works.
This is a very old question and I have no way of knowing if it was the OP's original problem, but I had the exact same scenario and this is how I resolved it.
For background: I have a WinForms application built using datasets and an Access database. I migrated that to use Sqlite and anything but datasets. To avoid destroying the application completely, first I copied the strongly typed data tables out, tweaked them to account for changes in the schema and then used PetaPoco to perform the data operations. That worked fine for a single test conversion.
The trouble arose when I wanted to move on and convert all data tables - I wasn't happy manually writing the logic for converting to and from typed data rows and POCOs, so I fell back to writing old school T4 templates to generate typed DataTable, DataRow classes and the necessary remapping code.
Worked a treat - for editing or removing data. But new rows disappeared on "creation", the binding navigator count didn't increment, and of course, when saving, I didn't detect any rows with the RowState of DataRowState.Added. The grid at start up was subtly different - a blank value in all columns instead of a negative number in the ID column. In hindsight, that should have been a big clue.
On reverting the behaviour back to the manually extracted typed class the grid started working again so it was clearly an error in the new code.
End of background; tldr;
The cause of the issue, in my case, was that the my Id column didn't have the AutoIncrement property set. As soon as I configured that to be true (along with setting AutoIncrementSeed and AutoIncrementStep to -1, although neither are required) new rows started being correctly added to the table.
Somewhat confused here, the following code causes changes in the DataTable when I would not expect it to do so. Is there no actual individual value change management inside of a DataTable? Or am I missing something?
var table = new DataTable();
table.Columns.Add("Name", typeof(string));
table.Rows.Add("Sample Name");
table.AcceptChanges();
table.Rows[0].SetField("Name", "Sample Name");
var changes = table.GetChanges();
// expecting null, actually returns changes
I would have expected internally the table to use some pre-built logic to determine whether or not the new value is indeed different from the current value.
Why is it done like this?
When you modify content of a row, it updates the DataRow.RowState property, which can hold UnChanged, Added, Modified etc. Later DataTable.GetChanges filter out rows based on that row status. It is irrespective of the value.
DataTable.GetChanges - MSDN
Gets a copy of the DataTable containing all changes made to it since
it was last loaded, or since AcceptChanges was called, filtered by
DataRowState.
Also see:
Row States and Row Versions - MSDN
ADO.NET manages rows in tables using row states and versions. A row
state indicates the status of a row; row versions maintain the values
stored in a row as it is modified, including current, original, and
default values. For example, after you have made a modification to a
column in a row, the row will have a row state of Modified, and two
row versions: Current, which contains the current row values, and
Original, which contains the row values before the column was
modified.
This is apparently a design feature as even calling the SetField() extension method with exactly the same object and then checking the field values in DataRowVersion.Original and DataRowVersion.Current you can find that they are still reference equal. There is no documentation describing a different behavior.
I am doing a small project to learn how to use DataSet but i have a small problem. Consider following code:
foreach (DatabaseDataSet.ApplicationRow rowApplication in database.Application)
{
if (rowApplication.AID.ToString() == lblIDApplication.Text)
{
rowApplication.Date= tbApplicationDatum.Text;
rowApplication.Status = tbApplicationStatus.Text;
applicationAdapter.Update(rowApplication);
break;
}
}
I don't know why but the database doesn't get updated. The DataRow is being updated as when I call the data again I see the new value. But when I re-run my application it's back to it's old value again. Any help?
EDIT: I'm working with strongly typed DataSet
You need to call the Update method of your adapter to propogate the changes
AcceptChanges only updates the changes in memory for the row and does not migrate those to the database
MSDN
AcceptChanges and RejectChanges only apply to DataRow related changes
(that is, Add, Remove, Delete, and Modify). They are not applicable to
schema or structural changes.
Calling AcceptChanges will not replicate these changes back to the
data source if the DataSet was filled using a DataAdapter. In that
situation, call Update instead
See Updating Data Sources with DataAdapters for more information
Its important to remember that the DataSet is a 'local copy' of the data not a 'live link' to the DB. If your DataSet is populated by a IDataAdaptor (say a TableAdaptor) for example you need to call the DataAdaptors Update method passing in the Updated dataset to sync the results back to the underlying DB.
Also I would suspect you DONT want to be doing 'new ApplicationTableAdapter()' because typically you would want to update with the TableAdaptor you populated with, at the least you would need to ensure you had the correct connection, query etc set up.
SOLUTION: It happens that nothing was wrong with the code. I had two ConnectionString defined in App.config. I forgot to remove the first one after I removed a previous database that had errors in it. Upon removing the first ConnectionString, everything worked.
I'm having some trouble getting my DataSet to work.
I have a MDB-Database in the background and created a DataSet out of it. Now I created a new method that lets me create a new user in the table.
But when I call it, nothing happens. No exceptions, no errors and I even get "1" returned as number of affected rows. But when I look in the database, no user was added.
I have the feeling that I miss to somehow tell the DataSet that I want to operate the Database itself rather than just the internal DataSet... How can I achieve this?
// DataSet1 uses the connection to the Database.mdb
// Created by the Designer
// The Users table has 3 columns, id, name and password
DataSet1 set = new DataSet1();
UsersTableAdapter adap = new UsersTableAdapter();
DataSet1.UsersRow row = set.Users.AddUsersRow("asd", "asd");
int count = adap.Insert("das", "das");
MessageBox.Show(row.RowState.ToString() + ": " + count.ToString());
count = adap.Update(set.Users);
set.AcceptChanges();
MessageBox.Show(row.RowState.ToString() + ": " + count.ToString());
// The Messagebox shows: "Added: 1"
// The second one: "Unchanged: 1"
MessageBox.Show(set.Users.Rows.Count.ToString());
// Returns "2"...
Not knowing too much about your code, try reading this how to from MSDN:
http://msdn.microsoft.com/en-us/library/ms233812(v=VS.80).aspx
Update: with data sets, what would normally happen (assuming the data set has been populated) is rows would be added, edited, or deleted in code. These rows would have a corresponding RowState signifying them as added, edited, deleted, or unmodified. During the .Update the associated table adapter, complete with associated insert/update/delete commands, will iterate the rows and execute the command on a given row depending on the row's state. When the rows have been iterated, .AcceptChanges is called, reverting the row state's to default.
If you call AcceptChanges before updating, then nothing will happen. The RowState of each row will be lost so the .Update will not have the required information it needs to perform the update to the database. If you have custom code for wrapping it all in a transaction, then you need to make sure you commit the transaction.
In your example, you seem to imply you are using the table adapter and not the data set itself. I would advise against this - the table adapters usually place methods on the tables in a data set that you should use.
Update 2: the code looks OK to me, though you don't need to call Insert on the adapter, or AcceptChanges after the update (the latter is done automatically). This leads me to believe there is a bug in your insert command SQL - try extracting the SQL used by the command and run it manually against the database.
Update 3: the following code works fine for me:
static void Main(string[] args)
{
db1DataSet set = new db1DataSet();
set.Users.AddUsersRow("asd", "asd");
foreach (DataRow row in set.Users.Rows)
{
object foo = row.RowState; // Confirm row state in debugger.
}
UsersTableAdapter adap = new UsersTableAdapter();
adap.Update(set.Users);
Console.Read();
}