DataAdapter: Update unable to find TableMapping['Table'] or DataTable 'Table' - c#

This code snippet is throwing an error:
Update unable to find TableMapping['Table'] or DataTable 'Table'.) on adapter.Update(ds); line
Why it is throwing this type of error?
SqlConnection con = new SqlConnection();
con.ConnectionString = connectionString();
DataSet ds = new DataSet();
string strQuery = "SELECT * FROM Cars";
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = new SqlCommand(strQuery, con);
SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
adapter.Fill(ds, "Cars");
//Code to modify data in the DataSet
ds.Tables["Cars"].Rows[0]["Brand"] = "NewBrand";
adapter.UpdateCommand = builder.GetUpdateCommand();
adapter.Update(ds);

Use
adapter.Update(ds, "Cars");
instead.
I have tested it. I got the same error without and it works if i specify the tablename. However, i must admit that i yet don't know why the DataAdapter needs to know the table-name since it has all informations it needs. If i useds.GetChanges i get one row with the correct table-name.
Update I have found nothing on MSDN but finally found it in the source(ILSpy). Here is the implementation of DBDataAdapter.Update(DataSet):
public override int Update(DataSet dataSet)
{
return this.Update(dataSet, "Table");
}
So if you don't specify a table, the table-name "Table" is used and if you've specified a table-name other than that you'll get this error, that's really strange!
I assume that the reason for this is that the DataAdapter cannot call GetChanges to determine the table to update for two reasons:
It would be inefficient since it needs to loop all tables and all of their rows to find rows with a RowState != Unchanged
It's possible that multiple tables needs to be updated since they contain changed rows. That is not supported via DataAdapter. Hence DataAdapter.Update(DataSet) assumes the default name "Table" as table-name.
Edit: However, maybe someone can explain me why the DataAdapter doesn't use DataSet.Tables[0].TableName instead.
So in general it seems to be best practise to specify the name of the table you want to update.

It's because .NET cannot assume that the table name in the DataSet/DataTable is identical to the database table. Thus .NET warns you about it.
To solve it you need to add a mapping to the DataAdapter:
da.TableMappings.Add("TableNameInDb", "TableNameInTheDataSet");
However, even if you have specified a name in the DataSet or the DataSource it still doesn't work, since the adapter seems to forget the name.
I only got it working by using:
da.TableMappings.Add("Table", "TableNameInDb");

I agree with jgauffin and I will only explain it with more text.
First, I must explain how TableMapping works. If we don't specify TableMappings with SqlDataAdapter (SqlDataAdapter that will fill our DataSet) then by default the first table will be named "Table", the second will be named "Table1", the third will be named "Table2" etc.
So, when we want to name DataTable in DataSet, we use it like this:
System.Data.DataSet myDataSet = new System.Data.DataSet();
using (System.Data.SqlClient.SqlDataAdapter dbAdapter = new System.Data.SqlClient.SqlDataAdapter(dbCommand))
{
dbAdapter.TableMappings.Add("Table", "Cars");
dbAdapter.TableMappings.Add("Table1", "Trucks");
//...
dbAdapter.Fill(myDataSet);
}
And only then we can modify it like this:
myDataSet.Tables["Cars"].Rows[0]["Brand"] = "Toyota";
myDataSet.Tables["Trucks"].Rows[0]["Brand"] = "MAN";

Related

The DataSet result is always empty in C#

I am retrieving particular column value using DataSet.
This is my code:
public DataSet GetRedirectURL(string emailId)
{
DataSet ds = new DataSet();
using (SqlConnection con = new SqlConnection(#"Connection_String_Here"))
{
con.Open();
SqlCommand sqlComm = new SqlCommand("usp_Login", con)
{
CommandType = CommandType.StoredProcedure
};
sqlComm.Parameters.AddWithValue("#EmailId", emailId);
SqlDataAdapter da = new SqlDataAdapter
{
SelectCommand = sqlComm
};
da.Fill(ds);
}
return ds;
}
I have also used DataTable instead of it but the same result.
I have checked my Stored Procedure and when I pass Parameter it shows Data. So, nothing wrong with the SP. But the Table doesn't show any data and is always empty as shown below:
What am I missing? Any help would be appreciated.
I'd suggest you to first evaluate the content of your DataSet. For instance, type in your Immediate Window (or add a quick watch) to check ds.Tables[0].Rows.Count. Basically, to assert your DataSet has been properly filled with the contents fetched from the database, and focus on the data assignment from the DataSet to the grid object you're using to display it.
Also, the .Fill() method has a returning object which is an int representing the amount of rows that have been successfully filled into the target object. For instance:
int result = da.Fill(ds);
Check the value of result after the .Fill() method has been executed.
Finally, I guess you're using a DataGridView object to visualize the results. If so, how are you binding data? Should be something like:
dataGridView1.DataSource = ds.Tables[0];
PS: As I've read in other comments, no, you don't need to execute the .Open() method on the connection. That's not necesarry, it's done implicitely when using the (using SqlConnection conn = SqlConnection..)

Read in a databse table but only get one field

I have a table with four text fields but when I execute the following I only get one field in the DataGridview. I am not geting all the records either I dont think. How to fix it so I get all the fields and records? text= table name this is in a function/method. Is it the query thats fouling things up?
string connetionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\temp\\Set.mdb;Persist Security Info=False";
string sql = "SELECT Property, PValue, PDefault, PType FROM "+text;
OleDbConnection connection = new OleDbConnection(connetionString);
OleDbDataAdapter dataadapter = new OleDbDataAdapter(sql, connection);
DataSet ds = new DataSet();
connection.Open();
dataadapter.Fill(ds, text);
connection.Close();
dataGridView1.DataSource = ds;
dataGridView1.DataMember = text;
There's a myriad of things that could be wrong. But none of them are evidenced in your question.
Your DataGridView might not have the correct columns added, or doesn't have AutoGenerateColumns = true.
You haven't mentioned if the data is actually missing from the dataset, or if it's just your view that's broken. Wouldn't you KNOW you're not getting all the records back? Not just have a hunch? Breakpoint that line, Sir!
Have you tried running that command directly on the database? Are the results good there?
I expect the answer will be that the data is fine, but the view is not showing all the data, Data...

Update using MySqlDataAdapter doesn't work

I am trying to use MySqlDatAdapter to update a MySql table. But, the table never updates!!! I did this before but with SQL server. Is there anything else that is specific to MySql that I am missing in my code?
DataTable myTable = new DataTable("testtable");
MySqlConnection mySqlCon = new MySqlConnection(ConfigurationManager.ConnectionStrings["DBConStr"].ConnectionString);
MySqlCommand mySqlCmd = new MySqlCommand("SELECT * FROM testtable WHERE Name = 'Tom'");
mySqlCmd.Connection = mySqlCon;
MySqlDataAdapter adapter = new MySqlDataAdapter(mySqlCmd);
MySqlCommandBuilder myCB = new MySqlCommandBuilder(adapter);
adapter.UpdateCommand = myCB.GetUpdateCommand();
mySqlCon.Open();
adapter.Fill(myTable);
myTable.Rows[0]["Name"] = "Was Tom";
myTable.AcceptChanges();
adapter.Update(myTable);
mySqlCon.Close();
Thanks
Remove myTable.AcceptChanges() before the update. Othwerwise that will set all rows RowState to Unchanged, hence the DataAdapter will not know that something was changed.
adapter.Update(myTable) will call AcceptChanges itself after the update is finished.
So...
myTable.Rows[0]["Name"] = "Was Tom";
//myTable.AcceptChanges();
adapter.Update(myTable);
My some one need to look into the following solution; In other scenario people may need different solution. Even Don't do any manipulation with Datatable when you Debug at Run-time like this,
myTable.GetChanges(); // Return Any of Chnages Made without applying myTable.Accepchanges()
myTable.GetChanges(DataRowState.Added); // Return added rows without applying myTable.Accepchanges()
myTable.GetChanges(DataRowState.Deleted);
myTable.GetChanges(DataRowState.Detached);
myTable.GetChanges(DataRowState.Modified);
myTable.GetChanges(DataRowState.Unchanged);
You may get Data According to the above commands. So better try to debug before you pass the datatable to update or insert or delete command.
If myTable.GetChanges() return null then you can SetAdded() or SetModified() back to your DataTable;
foreach(DataRow row in myTable.Rows)
{
row.SetAdded(); // For Insert Command
row.SetModified(); // For Update Command
}

Dataset holds a table called "Table", not the table I pass in?

I have the code below:
string SQL = "select * from " + TableName;
using (DS = new DataSet())
using (SqlDataAdapter adapter = new SqlDataAdapter())
using (SqlConnection sqlconn = new SqlConnection(connectionStringBuilder.ToString()))
using (SqlCommand objCommand = new SqlCommand(SQL, sqlconn))
{
sqlconn.Open();
adapter.SelectCommand = objCommand;
adapter.Fill(DS);
}
System.Windows.Forms.MessageBox.Show(DS.Tables[0].TableName);
return DS;
However, every time I run this code, the dataset (DS) is filled with one table called "Table". It does not represent the table name I pass in as the parameter TableName and this parameter does not get mutated so I don't know where the name Table comes from. I'd expect the table to be the same as the tableName parameter I pass in?
Any idea why this is not so?
EDIT: Important fact: This code needs to return a dataset because I use the dataRelation object in another method, which is dependent on this, and without using a dataset, that method throws an exception. The code for that method is:
DataRelation PartToIntersection = new DataRelation("XYZ",
this.LoadDataToTable(tableName).Tables[tableName].Columns[0],
// Treating the PartStat table as the parent - .N
this.LoadDataToTable("PartProducts").Tables["PartProducts"].Columns[0]);
// 1
// PartsProducts (intersection) to ProductMaterial
DataRelation ProductMaterialToIntersection =
new DataRelation("", ds.Tables["ProductMaterial"].Columns[0],
ds.Tables["PartsProducts"].Columns[1]);
Thanks
The default name for the first table in the DataSet is Table, the second one will be called Table1 and the third Table2 and so forth. The DataSet will not read the table name from the underlying store - and there's no option to make it do so.
This is documented behavior - see the MSDN documentation:
If the DataAdapter encounters multiple
result sets, it creates multiple
tables in the DataSet. The tables are
given an incremental default name of
TableN, starting with "Table" for
Table0. If a table name is passed as
an argument to the Fill method, the
tables are given an incremental
default name of TableNameN, starting
with "TableName" for TableName0.
If you want other names, you have to supply those - use this statement:
adapter.Fill(DS, Tablename);
This will name the newly filled table Tablename inside the DataSet.
The DataTable.TableName is just the name associated with the runtime structure and is independent of the data source used to create the DataTable.

Help with DataAdapter - DB doesn't update?

I have a data adapter. When I check the function at runtime I see the changes, but nothing happens in the database. How do I debug this? What went wrong?
OleDbDataAdapter adapter = new OleDbDataAdapter();
string queryString = "SELECT * FROM tasks";
OleDbConnection connection = new OleDbConnection(cn.ConnectionString);
adapter.SelectCommand = new OleDbCommand(queryString, connection);
OleDbCommandBuilder builder = new OleDbCommandBuilder(adapter);
connection.Open();
adapter.Fill(ds.Tables["Tasks"]);
adapter.Update(ds);
return ds;
Nothing is happening in the database because you're running a SELECT query. What are you expecting to happen?
Well unless you snipped a lot of code, you are not changing anything in the dataset per se.
What are you trying to achieve?
Here, you are selecting some data, filling the dataset with it, then putting back the unchanged dataset in the DB.
You should first change something in the dataset itself before calling adapter.Update(ds)
Cheers,
Florian
You are selecting data via the SelectCommand. If you want to update data, you need to run the UpdateCommand.
I assume you didn't post the full source code, as it looks as though you're not modifying the dataset. However, I just tweaked your code a bit (see my comments).
Hopefully this will help...
string queryString = "SELECT * FROM tasks";
OleDbConnection connection = new OleDbConnection(cn.ConnectionString);
connection.Open(); // open connection first
SqlCommand cmd = new SqlCommand(queryString, connection);
OleDbDataAdapter adapter = new OleDbDataAdapter(cmd); // use the cmd above when instantiating the adapter
OleDbCommandBuilder builder = new OleDbCommandBuilder(adapter);
adapter.Fill(ds.Tables["Tasks"]);
// Modify your dataset here.
// Don't call AcceptChanges() as this will prevent the update from working.
adapter.Update(ds);
connection.Close(); // Close connection before ending the function
return ds;
This should allow OleDbCommandBuilder to do its thing by automatically scripting the database updates.
As far as I can see you've not actually changed any of the contents of the tasks table. When you call adapter.Fill you are populated the empty dataset with the records from the database. You are then calling adapter.Update without changing any records within the dataset. The update command only performs changes when the dataset > datatable > datarows are edited and marked as dirty.
you are only specifying the select command. you also need to specify the insert command... i.e:
DataAdapter.InsertCommand = new OleDbCommand....

Categories