Datatable won't update my DB - c#

usersTableAdapter usersTA = new usersTableAdapter();
var usersTable = new users.usersDataTable();
usersTA.Fill(usersTable);
VK_BDayParser.users.usersRow row = usersTable.FindByid(currentItem.id);
row.BeginEdit();
row.last_name = "********";
row.EndEdit();
row.AcceptChanges();
usersTable.AcceptChanges();
int result = usersTA.Update(usersTable);
SQL server 2012.
I used generated classes from VS 2013 to database
I try to update row in my DB, in 'usersRow row' this changes works, but in DB has no changes. What am I doing wrong? result is always 0.

This is a common misunderstanding on what the AcceptChanges method does.
I think the problem arises from the initial comment in the documentation of the AcceptChanges method .
Commits all the changes made to this table since the last time
AcceptChanges was called.
Many people think that this means 'commits to the database table', instead it means 'commits to the in-memory instance of the datatable object'.
Then, the following comment on the docs, hints to what is really happening there.
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.
So, there is this DataRow.RowState property that express what is the current state of the in-memory rows belonging to the in-memory instance of the DataTable. And it is this state that helps the DataAdapter.Update method in discovering what to do with the rows.
In other words the Update method decides to update the database table only for the rows that are not RowState==DataRowState.Unchanged. But calling AcceptChanges 'commits' these rows and their state becomes Unchanged. No update then.

Related

c# Delete row from DataTable and use TableAdapter.Update and .Fill

Why is the DataTable not empty even after it has been cleared?
In the beginning I cleared the the "PasswoerterDataTable". But afte updating and filling it back it is not empty anymore. Did I misunderstood the usage of the .fill and .update commands? How do I correct my mistake so that the "PasswoerterDataTable" is empty in the end?
PasswoerterDataTable.Rows.Clear();
// DataTable is now empty
PasswoerterTableAdapter.Update(PasswoerterDataTable);
PasswoerterTableAdapter.Fill(PasswoerterDataTable);
// DataTable is not empty anymore. Why?
I know that it does not make sense to use .update and .fill after each other but I am currently working on a PasswordManager and I want to delete Passwords. These deleted Passwords should not appaer when the program is closed and started again but I need to use .fill after Startup to get the Passwords which haven't been deleted. But after I used .fill the Passwords reappear.
The Fill method exists to read data from a database table and put it inside an in memory DataTable object. I think you are misunderstanding the work of the Clear method and the Update method.
The Clear method removes all rows from the in memory datatable but doesn't change anything on the database table. The Update method looks at the rows present in your PasswoerterDataTable and checks their RowState property. If it finds something to update then a command is executed to reflect the changes back to the database.
But you have cleared the rows from PasswoerterDataTable so Update has nothing to update and your database table is left unchanged. The following Fill reloads everything.
If you want Update to execute delete commands on the database you need to set the RowState of each row to Deleted. And you can do this with
foreach(DataRow row in PasswoerterDataTable.Rows)
row.Delete(); // This doesn't remove the row, but sets its RowState to Deleted
// Now the adapter knows what to do...
PasswoerterTableAdapter.Update();
Of course this is totally unnecessary and you can simply write a single Command to act directly on your database to TRUNCATE your table
SqlCommand cmd = new SqlCommand("TRUNCATE TABLE PasswoerterTable", connection);
cmd.ExecuteNonQuery();
PasswoerterDataTable.Rows.Clear();
// No need to call Fill again.

RejectChanges Self-relation in DataSet

I have a problem rejecting a DataSet with self-related tables.
First I insert a parent row and a child row in a table. Then I call RejectChanges method from the table object or the same method from the DataSet. The RejectChagnes method throws RowNotInTableException.
This is the code to demostrate this (TestRejectChanges.zip):
DataSet dataSet = new DataSet();
//Parent row
DataSet.TABLERow parentRowOverDataSet = dataSet.TABLE.AddTABLERow(1, "Parent", null);
//Child row
dataSet.TABLE.AddTABLERow(2, "Child", parentRowOverDataSet);
//This line crash because the child row is detached before Rolback (in RejectChanges method code)
dataSet.TABLE.RejectChanges();
//Also crash
//foreach (DataSet.TABLERow row in dataSet.TABLE.ToList())
//{
// row.RejectChanges();
//}
//Also crash
//dataSet.RejectChanges();
I tryed to override RejectChanges of DataTable but this method is not virtual. Is there any way to do this using RejectChanges of DataSet?
I opened a MS Solve Case (using MSDN Lisence) and, after a month of waiting for their response, they wrote me the next:
I did some research and had discussed with one of our team member in
PG and this appears to be a by design issue as of now.
I went through your troubleshooting and suggestion:
Thanks a lot for you feedback on this issue. At this point of time, I
am going to file a DCR (Design Change Request) to see if they can
consider this functionality in up-coming release.
Then it has no solution by the moment.

TableAdapter Insert not persisting data

I created a service-based local db via Visual Studio 2013 Express edition.. The connection string, dataset and TableAdapter were added automatically.
On click of a button, I am trying to insert some data by calling TableAdapter.Insert
As it is I already have a dataGridView's datasource bound to the dataset, So I immediately see that the data was inserted in table properly at run time, But when I close the application, The actual DB dosn't contain the data. Therefore, The data isn't actually inserted in DB.
According to http://msdn.microsoft.com/en-us/library/ms233812%28v=vs.110%29.aspx
With insert, you have to only call insert, yet I am calling Update and AcceptChanges on table, for safety, well I tried the first way shown in link (i.e. creating a row and adding it to dataset then calling update) as well, but it seems the data isn't being inserted in DB at all.
Finally, the insert code, rds is DataSet and ta is TableAdapter
private void AddBtn_Click(object sender, EventArgs e)
{
ta.Insert("foo", "bar", 2, "zing", "tada");
ta.Fill(rds.reminders);
rds.reminders.AcceptChanges();
ta.Update(rds.reminders);
}
It turned out that, as I was using the VS compiled application each time the mdf database was being overwritten, hence the changes I made were completely erased,
The possible solution could be one of following
1)Change the connectionstring to point to database that is in Debug folder, which wont be overwritten each time you compile and run the application
2)You could simply let the connectionstring be as it is and just test it through detached compiler mode.
I was able to figure this out due to the following stackoverflow link I suddenly sumbled upon after 2 days.
Database changes do not persist after ObjectContext.SaveChanges() is called
ClearBeforeFill Property
http://msdn.microsoft.com/en-us/library/bz9tthwx.aspx
"By default, every time you execute a query to fill a TableAdapter's
data table, the data is cleared and only the results of the query are
loaded into the table."

Sync framework get conflicting row data

I am using Sync Framework to sync two Sql Server databases.
When some conflict is detected I catch the event and do some logic to resolve it, but I cant get the row data of the conflict.
So my question is, how can I get the specific conflicting data in the row that are about to synchronize?
The following code illustrates what I am doing:
if (e.Conflict.Type == DbConflictType.LocalInsertRemoteInsert)
{
DataTable conflictingRemoteChange = e.Conflict.RemoteChange;
}
When the ApplyChangeFailed event is raised by SqlSyncProvider, you use the DbApplyChangeFailedEventArgs object which provides information about the error or conflict that caused the failure. The e.conflict property contains moreover:
RemoteChange: Gets the DataTable object that contains the
conflicting rows from the remote database.
LocalChange: Gets the DataTable object that contains the conflicting rows from the local database.
These tables contain each one at most one row that represents the row in conflict.
Datarow drRemote = e.Conflict.RemoteChange.Rows[0];
Datarow drLocal = e.Conflict.LocalChange.Rows[0];
To get the specific value in conflict in the row, I'm afraid there is no other way that manually comparing of each value from the DataRows.
EDIT : #JuneT says that better than I ;-)
You can only get the rows in conflict. it will not tell you which
columns are in conflict. Sync Framework change tracking is at row
level. it simply logs that a row has changed and doesn't care what
changed.

Insert a DataRow inside a table

I have a function that returns a typed DataRow object and now I would insert this DataRow in a given table. As far as I know I could do this using TableAdapter in two ways: TableAdapter.Update and TableAdapter.Insert.
Both ways seems pretty simple to use but, first way could even delete row from the table (essentially my DataSet will be "serialized" on my DB table) and since this table is really the application's critical part I would avoid any chance of data deletion, so I would prefear Insert method.
The problem seems to be that Insert method doesn't accept a DataRow object as it's parameter (unlike Update), so I need to manually insert each parameters. Alas I have at least 80 parameters so this is a really really headache operation. What can I do now?
The update method does allow you to insert,update or delete changes in the tableAdapter. MSDN: 'Use the TableAdapter.Update method when your application uses datasets to store data. The Update method sends all changes (updates, inserts, and deletes) to the database'. Although Insert is ment for usage if you want more control for you data inserts but does not allow you to pass a datarow instead Parameters must be used. See complete reference on MSDN: http://msdn.microsoft.com/en-us/library/ms233812(v=vs.110).aspx
Code example of Update method usage.
// Create a new row.
NorthwindDataSet.RegionRow newRegionRow;
newRegionRow = northwindDataSet.Region.NewRegionRow();
newRegionRow.RegionID = 5;
newRegionRow.RegionDescription = "NorthWestern";
// Add the row to the Region table
this.northwindDataSet.Region.Rows.Add(newRegionRow);
// Save the new row to the database
this.regionTableAdapter.Update(this.northwindDataSet.Region);
Code example Insert:
NorthwindDataSetTableAdapters.RegionTableAdapter regionTableAdapter =
new NorthwindDataSetTableAdapters.RegionTableAdapter();
regionTableAdapter.Insert(5, "NorthWestern");

Categories

Resources