SqlAdapter.Update() method perform insertion instead of updation - c#

I used SqlAdapter.Update() method to update the rows in a table.
For that I created Datatable and add values to that datatable.
DataTable dtTable = new DataTable("Product");
SqlConnection myLocalConnection = new SqlConnection(_ConnectionString);
SqlDataAdapter mySqlDataAdapter = new SqlDataAdapter("Select * from " + dtTable.TableName, myLocalConnection);
SqlCommandBuilder mySqlCommandBuilder = new SqlCommandBuilder(mySqlDataAdapter);
mySqlDataAdapter.Update(dtTable);
When I using this command it insert new rows in the database rather than updating the existing rows. Why does this happen?

I think what is happening here is (As per your given code) your dataadapter is unable to recognize rows in your datatable it is nowhere related to your datatable here, So as a guess try to fill your datatable via dataadapter then modify your datatable and update it.
DataTable dtTable = new DataTable();
SqlConnection myLocalConnection = new SqlConnection(_ConnectionString);
SqlDataAdapter mySqlDataAdapter = new SqlDataAdapter("Select * from " +
dtTable.TableName, myLocalConnection);
SqlCommandBuilder builder= new SqlCommandBuilder(mySqlDataAdapter);
mySqlDataAdapter.Fill(dtTable,"Products" )
// Code to modify your datatable
mySqlDataAdapter.UpdateCommand = builder.GetUpdateCommand();
mySqlDataAdapter.Update(dtTable);
-- Hope it helps .

This is just an idea and not the solution...
// update command to update database table.
string strUpdateCommand =
"Update Students set Name = #Name, Gender = #Gender, Total = #Total where ID = #ID";
// create an instance of SqlCommand using the update command created above.
SqlCommand updateCommand = new SqlCommand(strUpdateCommand, con);
// specify the paramaters of the update command.
updateCommand.Parameters.Add("#Name", SqlDbType.NVarChar, 50, "Name");
updateCommand.Parameters.Add("#Gender", SqlDbType.NVarChar, 20, "Gender");
updateCommand.Parameters.Add("#Total", SqlDbType.Int, 0, "Total");
updateCommand.Parameters.Add("#ID", SqlDbType.Int, 0, "ID");
// associate update command with SqlDataAdapter instance.
dataAdapter.UpdateCommand = updateCommand;

Related

Can not Insert into Database with SqlDataAdapter and MSSqlServer in c#

I want to insert new record into the DataTable with DataAdapter.
There are 2 columns in Person table. FirstName and LastName.
I have a code like below.
SqlConnection connection;
DataSet dsPerson;
SqlDataAdapter adapter;
string connectionString = Properties.Resources.ConnectionString;
connection = new SqlConnection(connectionString);
dsPerson = new DataSet("PersonDataSet");
adapter = new SqlDataAdapter();
SqlCommand selectCommand = new SqlCommand("SELECT * FROM Person", connection);
adapter.SelectCommand = selectCommand;
adapter.Fill(dsPerson, "Person");
string insertQuery = "INSERT INTO Person(FirstName, LastName) VALUES (#FirstName, #LastName)";
SqlCommand insertCommand = new SqlCommand(insertQuery, connection);
insertCommand.Parameters.Add(new SqlParameter("#FirstName", SqlDbType.NVarChar));
insertCommand.Parameters["#FirstName"].SourceVersion = DataRowVersion.Current;
insertCommand.Parameters["#FirstName"].SourceColumn = "FirstName";
insertCommand.Parameters.Add(new SqlParameter("#LastName", SqlDbType.NVarChar));
insertCommand.Parameters["#LastName"].SourceVersion = DataRowVersion.Current;
insertCommand.Parameters["#LastName"].SourceColumn = "LastName";
adapter.InsertCommand = insertCommand;
But when I try to insert new Record into DataSet it appears in the DataSet. But it does not do insert new record into DataBase.
The Code for Insert is below.
connection.Open();
DataRow newRow = dsPerson.Tables["Person"].NewRow();
newRow["FirstName"] = "Joseph";
newRow["LastName"] = "Sword";
dsPerson.Tables["Person"].Rows.Add(newRow);
dsPerson.Tables["Person"].AcceptChanges();
dsPerson.AcceptChanges();
adapter.Update(dsPerson, "Person");
connection.Close();
I even try to trace queries sent to sql server With Express Profiler. And i saw that it does not send insert command to the database.
So what is the problem? How to solve it?
Thank you.
You should not call AcceptChanges methods of dataset and DataTable because DataAdapter.Update method affects only changed/added/deleted rows from datatable.
But after calling AcceptChanges all your DataRows will have Unchanged state.
See MSDN for reference about DataAdapter:
When an application calls the Update method, the DataAdapter examines
the RowState property, and executes the required INSERT, UPDATE, or
DELETE statements iteratively for each row, based on the order of the
indexes configured in the DataSet.

How to Use an Update Statement in SQLDataAdapter

I am trying to run an update statement after i built my sqldataadapter. I have column called INIT_PHASE in my table and if the INIT_PHASE is null or there is no data then i would like to set it to 1. I have tried but i can't seem to get it right the update statement. Pls. help. here is my code:
string ID = ddlPractice.SelectedValue;
string TYPE = DDL_TYPE.SelectedValue;
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["myConnection"].ConnectionString);
SqlDataAdapter da = new SqlDataAdapter(#"select SET_SK, UNIT_NM, TYPE, INIT_PHASE FROM myTable WHERE UNIT_NM =#ID AND TYPE = #TYPE", con);
DataTable dtSETS = new DataTable();
da.SelectCommand.Parameters.AddWithValue("#ID", (ID));
da.SelectCommand.Parameters.AddWithValue("#TYPE", (TYPE));
da.Fill(dtSETS);
if (dtSETS.Rows.Count > 0)
{
DataRow dtSETS_row = dtSETS.Rows[0];
long SET_SK = dtSETS_row.Field<long>("SET_SK");
if (dtSETS_row.Field<string>("INIT_PHASE") == null)
{
//run update command here
update myTable set INIT_PHASE = 1;
}
}
One approach here would be to use the SqlCommandBuilder to build the UPDATE statement:
string ID = ddlPractice.SelectedValue;
string TYPE = DDL_TYPE.SelectedValue;
SqlConnection con = new SqlConnection(
ConfigurationManager.ConnectionStrings["myConnection"].ConnectionString);
SqlDataAdapter da = new SqlDataAdapter(
#"select SET_SK, UNIT_NM, TYPE, INIT_PHASE FROM myTable WHERE UNIT_NM =#ID AND TYPE = #TYPE",
con);
DataTable dtSETS = new DataTable();
da.SelectCommand.Parameters.AddWithValue("#ID", (ID));
da.SelectCommand.Parameters.AddWithValue("#TYPE", (TYPE));
da.Fill(dtSETS);
SqlCommandBuilder builder = new SqlCommandBuilder(da);
da.UpdateCommand = builder.GetUpdateCommand();
if (dtSETS.Rows.Count > 0)
{
DataRow dtSETS_row = dtSETS.Rows[0];
long SET_SK = dtSETS_row.Field<long>("SET_SK");
if (dtSETS_row.Field<string>("INIT_PHASE") == null)
{
dtSETS_row["INIT_PHASE"] = 1;
}
}
da.Update(dtSETS);
Take note to the following lines of code. Here we are building the update command:
SqlCommandBuilder builder = new SqlCommandBuilder(da);
da.UpdateCommand = builder.GetUpdateCommand();
here we are literally modifying the DataRow so that it's RowState is changed to Modified:
dtSETS_row["INIT_PHASE"] = 1;
and then finally, here we are sending updates to the database with the Update method on the SqlDataAdapter:
da.Update(dtSETS);
What this is going to do is only send updates for the rows with a RowState of Modified.
NOTE: each of the ADO.NET objects should be wrapped in a using. Refactor your code to match this type of template:
using (SqlConnection con = new SqlConnection(...))
{
using (SqlDataAdapter da = new SqlDataAdapter(...))
{
}
}
If I understand correctly, you could execute directly a command to update just this field
if (dtSETS_row.Field<string>("INIT_PHASE") == null)
{
SqlCommand cmd = new SqlCommand(#"UPDATE myTable set INIT_PHASE = 1 " +
"WHERE UNIT_NM =#ID AND TYPE = #TYPE", con);
cmd.Parameters.AddWithValue("#ID", (ID));
cmd.Parameters.AddWithValue("#TYPE", (TYPE));
cmd.ExecuteNonQuery();
}
You need to open the connection though both for the SqlDataAdapter and for the following command
You will have to use SqlCommandBuilder class for updating data in disconnected mode. ie) DataSet and Data Adapters.

SQL DataTable Update?

I'm not sure, but I think I may have taken a wrong path here. I am trying to update my customer table on my SQL Server. I Connected with a SQLDatareader and then loaded that into my Datatable. I have made all the changes I wanted and now I can't figure out how to get the changes back up. I thought that the "myDataTable.AcceptChanges();" would trigger that to happen but it doesn't.
SqlConnection myConnection = new SqlConnection();
SqlCommand myCommand;
DataTable myDataTable;
SqlDataReader myReader;
myCommand = new SqlCommand();
myCommand.CommandText = " SELECT * FROM customer";
myCommand.CommandType = CommandType.Text;
myCommand.Connection = myConnection;
myCommand.Connection.Open();
myReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection);
myDataTable = new DataTable();
myDataTable.Load(myReader);
// Make Data changes here
myDataTable.AcceptChanges();
MyDataTable.Dispose();
MyCommand.Dispose();
MyConnection.Dispose();
You can use a TableAdapter to commit your changes back to the database. Check out this link for details.
TableAdapter.Update()
In such case you need to use a DataAdapter which has an Update property that takes your Update Query Command.
Even you can use Command Builder and then get the UpdateCommand from CommandBuilder.
Sample Code from MSDN
SqlDataAdapter catDA = new SqlDataAdapter("SELECT CategoryID, CategoryName FROM Categories", nwindConn);
catDA.UpdateCommand = new SqlCommand("UPDATE Categories SET CategoryName = #CategoryName " +
"WHERE CategoryID = #CategoryID" , nwindConn);
catDA.UpdateCommand.Parameters.Add("#CategoryName", SqlDbType.NVarChar, 15, "CategoryName");
SqlParameter workParm = catDA.UpdateCommand.Parameters.Add("#CategoryID", SqlDbType.Int);
workParm.SourceColumn = "CategoryID";
workParm.SourceVersion = DataRowVersion.Original;
DataSet catDS = new DataSet();
catDA.Fill(catDS, "Categories");
DataRow cRow = catDS.Tables["Categories"].Rows[0];
cRow["CategoryName"] = "New Category";
catDA.Update(catDS);
MSDN Link

update table in database from datatable

I load data from database table like this...
using (view_adapter = new SqlDataAdapter("select * from TVServiceProvider", connection_string))
{
using (dt = new DataTable())
{
view_adapter.Fill(dt);
for (int i = 0; i < dt.Columns.Count; i++)
{
if (dt.Columns[i].ColumnName.Substring(0, 2).Equals("id"))
dt.Columns[i].ReadOnly = false;
}
bs.DataSource = dt;
}
}
Where SqlDataAdapter view_adapter and DataTable dt. To apply changes to database I've created method
void View_Adapter_Click(object sender, EventArgs e)
{
try
{
view_adapter.Update(dt);
dt.AcceptChanges();
}
catch (Exception exc)
{
this.radLabelElement1.Text = exc.Message;
}
}
But when I click the button I've got an exception. It requires update command. Where and what command I should use?
You must create UpdateCommand and DeleteCommand for you view_adapter.
EDIT:
The code must look like this:
SqlDataAdapter view_adapter = new SqlDataAdapter();
view_adapter .SelectCommand = new SqlCommand(queryString, connection);
view_adapter .UpdateCommand = new SqlCommand(updateCommadString, connection);
view_adapter .DeleteCommand = new SqlCommand(deleteCommadString, connection);
using (SqlConnection connection = new SqlConnection(connectionString))
{
view_adapter.Fill(dt);
return dt;
}
Well, something is wrong or not clear in your code.
The view_adapter variable is initialized within a using block statement.
Thus, when exiting from the using block, the view_adatpter will be disposed by the framework and unusable in the click event. (like you have never called new to initialize it).
I suspect that you have another problem here. Using statement
A part from this, to automatically create the UpdateCommand, InsertCommand and DeleteCommand required to perform CRUD operations with a DataAdapter you could use a SqlCommandBuilder.
(This is possible only if you use one table in the select statement and that table has a primary key defined)
So to summarize everything:
string queryString = "select * from TVServiceProvider";
view_adapter = new SqlDataAdapter(queryString, connection_string);
SqlCommandBuilder builder = new SqlCommandBuilder(view_adapter)
builder.GetUpdateCommand(); // Force the building of commands
view_adapter.Fill(dt);
then your click event should works as is now.
This code is not related to yours, but may help you, If you give it a look. I got it from MSDN
public static SqlDataAdapter CreateCustomerAdapter(
SqlConnection connection)
{
SqlDataAdapter adapter = new SqlDataAdapter();
// Create the SelectCommand.
SqlCommand command = new SqlCommand("SELECT * FROM Customers " +
"WHERE Country = #Country AND City = #City", connection);
// Add the parameters for the SelectCommand.
command.Parameters.Add("#Country", SqlDbType.NVarChar, 15);
command.Parameters.Add("#City", SqlDbType.NVarChar, 15);
adapter.SelectCommand = command;
// Create the InsertCommand.
command = new SqlCommand(
"INSERT INTO Customers (CustomerID, CompanyName) " +
"VALUES (#CustomerID, #CompanyName)", connection);
// Add the parameters for the InsertCommand.
command.Parameters.Add("#CustomerID", SqlDbType.NChar, 5, "CustomerID");
command.Parameters.Add("#CompanyName", SqlDbType.NVarChar, 40, "CompanyName");
adapter.InsertCommand = command;
// Create the UpdateCommand.
command = new SqlCommand(
"UPDATE Customers SET CustomerID = #CustomerID, CompanyName = #CompanyName " +
"WHERE CustomerID = #oldCustomerID", connection);
// Add the parameters for the UpdateCommand.
command.Parameters.Add("#CustomerID", SqlDbType.NChar, 5, "CustomerID");
command.Parameters.Add("#CompanyName", SqlDbType.NVarChar, 40, "CompanyName");
SqlParameter parameter = command.Parameters.Add(
"#oldCustomerID", SqlDbType.NChar, 5, "CustomerID");
parameter.SourceVersion = DataRowVersion.Original;
adapter.UpdateCommand = command;
// Create the DeleteCommand.
command = new SqlCommand(
"DELETE FROM Customers WHERE CustomerID = #CustomerID", connection);
// Add the parameters for the DeleteCommand.
parameter = command.Parameters.Add(
"#CustomerID", SqlDbType.NChar, 5, "CustomerID");
parameter.SourceVersion = DataRowVersion.Original;
adapter.DeleteCommand = command;
return adapter;
}
What actually worked for me from Steve and Hamlet's suggestions is the following. I had one hiccup because I tried to do an accept changes on my rows and table before doing the view adapter update. The accept changes in only needed to save the changes to the datatable before reusing the datatable for displaying in a gridview or other operations.
SqlDataAdapter viewAdapter = new SqlDataAdapter("Select * From Users", DBConn);
SqlCommandBuilder builder = new SqlCommandBuilder(viewAdapter);
viewAdapter.UpdateCommand = builder.GetUpdateCommand();
DataTable Users = new DataTable();
viewAdapter.Fill(Users);
foreach (DataRow user in Users.Rows)
{
foreach (DataColumn c in Users.Columns)
{
Console.WriteLine(c.ColumnName);
if (c.DataType != typeof(DateTime))
{
// Clean up empty space around field entries
user[c.ColumnName] = user[c.ColumnName].ToString().Trim();
}
}
// user.AcceptChanges();
// Do not do an accept changes for either the table or the row before your ViewAdapter Update.
// It will appear as though you do not have changes to push.
}
// Users.AcceptChanges();
viewAdapter.Update(Users);

ADO.NET - Updating Multiple DataTables

So I have some code like this:
DataSet dataSet = new DataSet();
DataTable dataTable1 = new DataTable("Table1");
DataTable dataTable2 = new DataTable("Table2");
DataTable dataTable3 = new DataTable("Table3");
DataTable dataTable4 = new DataTable("Table4");
dataSet.Tables.Add(dataTable1);
dataSet.Tables.Add(dataTable2);
dataSet.Tables.Add(dataTable3);
dataSet.Tables.Add(dataTable4);
SqlDataAdapter dataAdapter1 = new SqlDataAdapter("SELECT * FROM Table1 WHERE ID = 1", sqlConnection);
SqlDataAdapter dataAdapter2 = new SqlDataAdapter("SELECT Column1, Column2, Column3 FROM Table2", sqlConnection);
SqlDataAdapter dataAdapter3 = new SqlDataAdapter("SELECT Column1, Column2, Column3 FROM Table3", sqlConnection);
SqlDataAdapter dataAdapter4 = new SqlDataAdapter("SELECT Column1, Column2, Column3 FROM Table4", sqlConnection);
SqlCommandBuilder commandBuilder1 = new SqlCommandBuilder(dataAdapter1);
SqlCommandBuilder commandBuilder2 = new SqlCommandBuilder(dataAdapter2);
SqlCommandBuilder commandBuilder3 = new SqlCommandBuilder(dataAdapter3);
SqlCommandBuilder commandBuilder4 = new SqlCommandBuilder(dataAdapter4);
dataAdapter1.Fill(dataTable1);
dataAdapter2.FillSchema(dataTable2, SchemaType.Source);
dataAdapter3.FillSchema(dataTable3, SchemaType.Source);
dataAdapter4.FillSchema(dataTable4, SchemaType.Source);
//do a bunch of code that updates the one row from Table1
//and adds lots of new rows to Table2, Table3, Table4
dataAdapter1.Update(dataTable1);
dataAdapter2.Update(dataTable2);
dataAdapter3.Update(dataTable3);
dataAdapter4.Update(dataTable4);
dataSet.AcceptChanges();
Is there anyway to make this a lot simpler? What would happen if the computer crashed on the line after "dataAdapter2.Update(dataTable2);"? I would like to be able to somehow use just one Update call to update everything. Is that possible?
Also, is this even the best way to do this? With "this" being creating a bunch of new rows in multiple tables depending on what is in one specific row in one specific table.
You can pass a dataset into a DataAdapter's Update statement, which will update all of the tables in the dataset. UPDATE: No, it doesn't. DataAdapters always update only one table. The overload to Update() that takes a DataSet as its parameter, from the MSDN documentation, "Calls the respective INSERT, UPDATE, or DELETE statements for each inserted, updated, or deleted row in the specified DataSet from a DataTable named "Table"." Sorry for the confusion. The rest of the answer is still valid, though.
If you want to assure that all the updates succeed or fail as an atomic unit, use the SqlTransaction object:
DataSet ds = new DataSet();
// do something with the dataset
SqlDataAdapter dataAdapter = new SqlDataAdapter();
SqlConnection cn = new SqlConnection(connString);
cn.Open();
SqlTransaction trans = cn.BeginTransaction();
SqlDataAdapter dataAdapter = new SqlDataAdapter();
// set the InsertCommand, UpdateCommand, and DeleteCommand for the data adapter
dataAdapter.InsertCommand.Transaction = trans;
dataAdapter.UpdateCommand.Transaction = trans;
dataAdapter.DeleteCommand.Transaction = trans;
try
{
dataAdapter.Update( ds );
trans.Commit();
}
catch
{
trans.Rollback();
}
cn.Close();

Categories

Resources