I have read from many places that it is possible to fill a DataSet with multiple tables using a DataAdapter. It also does not say whether a single Update call can update all the tables in the DataSet.
Can someone help me figure out how this can be done?
It seems like there isn't any ( i tried finding online ) examples on how to do it except for one that changes the SelectCommand on the DataAdapter before the second fill. But I feel this method defeats the purpose of the DataAdapter.
From what I figure, perhaps a single DataAdapter can only handle a single database table and Update only works on that table. Hence a multi-table DataSet will require respective DataAdapters call their Update to fully update the DataSet. Is this the case?
Finally, will foreign key relations and contraints hold in a DataSet (cascade delete, cascade update) automatically?
Maybe a link to an example or tutorial might help. Many thanks!
Yes it is true that, Single Adapter for single table.But
You can use Use table adapter manager for saving all at once, table adapter manager can have many individual adapters and you can call save for all. like, So no need to call save multiple time also it has other features too.
public void SaveWithManager()
{
DataSet1TableAdapters.TableAdapterManager mgr1 = new DataSet1TableAdapters.TableAdapterManager();
DataSet1TableAdapters.Table1TableAdapter taTbl1 = new DataSet1TableAdapters.Table1TableAdapter();
DataSet1TableAdapters.Table2TableAdapter taTbl2 = new DataSet1TableAdapters.Table2TableAdapter();
mgr1.Table1TableAdapter = taTbl1;
mgr1.Table2TableAdapter = taTbl2;
mgr1.UpdateOrder = DataSet1TableAdapters.TableAdapterManager.UpdateOrderOption.InsertUpdateDelete;
mgr1.UpdateAll(your dataset);
}
Finally cascade update delete is handled in dataset. You can view properties of relation and various options for cascade.(Typed dataset)
Related
I'm working on a simple userclient (frontend) for a MS SQL Server database.
The database itself is pretty straight forward, there are eight tables without any foreign keys.
So far I managed to connect to the database and load all tables and data into a dataset.
I'm doing this by using a single string with multiple SQL-Statements (one for each table):
_dbconstrb = new SqlConnectionStringBuilder();
_dbconstrb.DataSource = ".\local";
_dbconstrb.InitialCatalog = "mydatabase";
string sql_str = "SELECT * FROM tbl1; SELECT * FROM tbl2; ..."
_dbda = new SqlDataAdapter(sql_str, _sqlcon);
_dbds = new DataSet();
_dbda.Fill(_dbds);
The dataset is bind to a bindingsource and this is set as datasource for a DataGridView. I'm using a simple ComboBox, where the user can select one of the eight database tables. Everytime the user makes any change on the combobox, the datamember of the bindingsource is set to selected table from the combobox. So far it works perfect.
Now the user will make any changes in the gridview data (add, delete or change records).
I would like to update the database by using the SQLCommandBulider and I tried this:
SqlCommandBuilder cmb = new SqlCommandBuilder(_dbda);
int updated = _dbda.Update(_dbds);
However this only works on the data of the first table (the table which comes first in the sql-string, in this case it is tbl1). It seems that all followed tables are not recognized by the DataAdapter. Do I really have to use eight DataAdapters (one for each table) to achieve this?
Solution:
Finally I managed this by adding eight DataApter. However, the Entity Framework looks very promising for such kind of datahandling. Again thanx for that point.
although your application might be simple not sure if loading the data from all the tables is good idea in terms of performance. I think using entity framework will help you http://www.asp.net/web-forms/overview/working-with-data-(entity-framework-tutorial)
and its really simple for what you are trying to do.
I've a SQLCe database with a table. In the application there is a method which should only inserting new rows to this table.
I'm wondering what is the best practise for doing so. When working with a DataSet one has to load the whole table into it.
To me this seems like a big overkill, since I only want to insert new rows and therefore there is no need to fill the DataSet with the entire table.
On the other hand it also seems very ineffective to manually insert every single row with an explicit INSERT statement.
So in order to do a "batch"-INSERT one would go with a DataSet. Is there a possibility to work with a DataSet without filling the entire table, e.g. get only the schema of the table and then insert the rows to the DataSet?
Many thanks,
Juergen
Working with DataSet against a SQL Server Compact database is vey inefficient . you should use SqlCeResultSet or my wrapper lbrar, that allows you to do batch INSERTs very fast, based on a DataTable, a DataReader or even a List of objects. http://sqlcebulkcopy.codeplex.com
I have a DataSet with two TableAdapters (1 to many relationship) that was created using visual studio 2010's Configuration Wizard.
I make a call to an external source and populate a Dictionary with the results. These results should be all of the entries in the database. To synchronize the DB I don't want to just clear all of the tables and then repopulate them like dropping the tables and creating them with new data in sql.
Is there a clean way possibly using the TableAdapter.Fill() method or do I have to loop through the two tables row by row and decide if it stay or gets deleted and then add the new entries? What is the best approach to make the data that is in the dictionary be the only data in my two tables with the DataSet?
First Question: if it's the same DB why do you have 2 tables with the same information?
To the question at hand: that largley depend on the sizes. If the tables are not big then use a transaction, clear the table (DELETE * FROM TABLE or whatever) and write your data in there again.
If the tables are big on the other hand the question is: can you load all this into your dictionary?
Of course you have to ask yourself what happens to inconsistent data (another user/app changed the data while you had it in your dictionary).
If this takes to long you could remember what you did to the data - that means: flag the changed data and remember the deleted keys and new inserted rows and make your updates based on that.
Both can be achieved by remembering the Filled DataTable and use this as backing field or by implementing your own mechanisms.
In any way I would recommend think on the problem: do you really need the dictionary? Why not make queries against the database to get the data? Or only cache a part of the data for quick access?
PS: the update method on you DataAdapter will do all the work (changing the changed, removing the deleted and inserting the new datarows but it will update the DataTable/Set so this will only work once)
It could be that it is quicker to repopulate the entire table than to itterate through and decide what record go / stay. Could you not do the process of deciding if a records is deleteed via an sql statement ? (Delete from table where active = false) if you want them to stay in the database but not in the dataset (select * from table where active = true)
You could have a date field and select all records that have been added since the date you late 'pooled' the database (select * from table where active = true and date-added > #12:30#)
I'm having an issue with writing back to my Access Database (.accdb) through using a DataAdapter.
Currently, I have a Fill method which fills a DataSet Table up with data. This piece of code is currently sitting within my Form_Load().
// TODO: This line of code loads data into the 'hCAliasDataSet.Topics' table. You can move, or remove it, as needed.
this.topicsTableAdapter.Fill(this.hCAliasDataSet.Topics);
Then I have an cmdAdd_Click() event, this is obviously to add a new row into the Topcis table that sits within the hCAliasDataSet.
// Create a new row, append it to Topics table.
DataRow DR;
DR = this.hCAliasDataSet.Tables["Topics"].NewRow();
this.hCAliasDataSet.Tables["Topics"].Rows.Add(DR);
Next, I've created some code to caputre the input of one of the column values.
// Capture user input
sTopicName = Interaction.InputBox("Please Enter Topic Name", "Topic Name", null, 100, 100);
// Set the Topic value for the new Row
DR["Topic"] = sTopicName;
My problem, I'm assuming is here, where I call the dataAdapter to update the Topics table. I manually check the database, and there aren't any new rows created?
// Commit the changes back to the hCAlias DataBase (hcalias.accdb).
this.topicsTableAdapter.Update(this.hCAliasDataSet.Topics);
Edit: I believe I'm needing to create an INSERT query, for my TableAdapter, would this be correct?
The adapter should generate the insert statement automatically for you behind the scenes.
Your code looks right, but it's possible that you have a constraint on one of your columns that makes it unable to save. (like a non-nullable column that you didn't specify any data for). But, you'd usually get an exception if there was a constraint that cancelled the insert.
You can try one of these alternatives, but they're basically the same thing:
this.topicsTableAdapter.Update(this.hCAliasDataSet);
this.topicsTableAdapter.Update(DR);
this.topicsTableAdapter.Insert(sTopicName); // add any other columns in here
You should call AcceptChanges in your dataset:
hCAliasDataSet.AcceptChanges();
And then commit to the database with your TableAdapter.
The Update() method just updates existing records, you'll need to use the TableAdapter Insert() method to add a new row. VC# will have created a default Insert() method for you, (which may be overloaded)... but there will be a method that will let you explicitly insert values....
For example...
this.topicsTableAdapter.Insert(int Column1, string Column2 etc etc)
This will create a new row in your database and populate it with the values you specify.
i have a many-to-many relationship table in a typed DataSet.
For convenience on an update i'm deleting old relations before i'm adding the new(maybe the same as before).
Now i wonder if this way is failsafe or if i should ensure only to delete which are really deleted(for example with LINQ) and only add that one which are really new.
In SQL-Server is a unique constraint defined for the relation table, the two foreign keys are a composite primary key.
Is the order the DataAdapter updates the DataRows which RowState are <> Unchanged predictable or not?
In other words: is it possible that DataAdapter.Update(DataTable) will result in an exception when the key already exists?
This is the datamodel:
This is part of the code(LbSymptomCodes is an ASP.Net ListBox):
Dim daTrelRmaSymptomCode As New ERPModel.dsRMATableAdapters.trelRMA_SymptomCodeTableAdapter
For Each oldTrelRmaSymptomCodeRow As ERPModel.dsRMA.trelRMA_SymptomCodeRow In thisRMA.GettrelRMA_SymptomCodeRows
oldTrelRmaSymptomCodeRow.Delete()
Next
For Each item As ListItem In LbSymptomCodes.Items
If item.Selected Then
Dim newTrelRmaSymptomCodeRow As ERPModel.dsRMA.trelRMA_SymptomCodeRow = Services.dsRMA.trelRMA_SymptomCode.NewtrelRMA_SymptomCodeRow
newTrelRmaSymptomCodeRow.fiRMA = Services.IdRma
newTrelRmaSymptomCodeRow.fiSymptomCode = CInt(item.Value)
Services.dsRMA.trelRMA_SymptomCode.AddtrelRMA_SymptomCodeRow(newTrelRmaSymptomCodeRow)
End If
Next
daTrelRmaSymptomCode.Update(Services.dsRMA.trelRMA_SymptomCode)
Thank you in advance.
I think that the DataAdapter in ADO.NET is clever enough to perform the delete/inserts in the correct order.
However, if you really want to ensure that updates are done in the correct order you should do it manually by using the Select method to return an array of data rows for each particular row state. You could then call the Update method on the array of data rows
DataTable tbl = ds.Tables["YourTable"];
// Process any Deleted rows first
adapter.Update(tbl.Select(null, null, DataViewRowState.Deleted));
// Process any Updated/Modified rows
adapter.Update(tbl.Select(null, null, DataViewRowState.ModifiedCurrent));
// Process the Inserts last
adapter.Update(tbl.Select(null, null, DataViewRowState.Added));
Not sure about the DA but in theory DB transactions should be performed in the following order Deletes, Inserts, Updates.
looking at msdn the exact wording for the update method is
Blockquote
Attempts to save all changes in the DataTable to the database. (This includes removing any rows deleted from the table, adding rows inserted to the table, and updating any rows in the table that have changed.)
Blockquote
In regards to your solution of deleting items and possibly re-inserting the same items, typically speaking this should be avoided because it creates a load on the DB. In high volume applications you want to do everything you can to minimize calls to the DB as they are very expensive; computation time, from determining which row updates are spurious, is cheap.