How to update MySql table row through C# console application? - c#

I am writing a console application and fetch data from MySql table .
Code :
string connection = "Server=localhoht;Database=data;Uid=root;Pwd=root123";
MySqlConnection dbcon = new MySqlConnection(connection);
MySqlCommand selectData;
dbcon.Open();
selectData = dbcon.CreateCommand();
selectData.CommandText = "SELECT user_id, user_name,user_type FROM win_user WHERE user_type=1 ORDER BY user_id ASC ";
MySqlDataReader juh = selectData.ExecuteReader();
And its working fine. Now I want to update a row with the code below :
string updatedata = "UPDATE win_user SET user_type='1' WHERE user_id= '1'";
MySqlDataAdapter MyData = new MySqlDataAdapter();
MyData.UpdateCommand = new MySqlCommand(updatedata, dbcon);
But its not working.

You can run the commend "UPDATE win_user SET user_type='1' WHERE user_id= '1'" in any sql client tools, eg, navicat, to verify wheather it's correct on your mysql database.

The MySqlDataAdapter could be used to update rows in a database table using the Update method.
The Update method (link is for SqlServer but the concept is the same) has many overload, but basically it requires a DataTable with rows modified in some way ([RowState != DataRowState.Unchanged][2]) so the MySqlDataAdapter can pick the rows changed and apply the DeleteCommand, UpdateCommand and InsertCommand defined in the adapter
Your code above doesn't shown any kind of interaction with a datatable and you have a call to the Update method so there is no way for the update to occur.
You could, of course execute directly your command without any adapter involved
EDITed to change every user_type not 1 to 1
string updatedata = "UPDATE win_user SET user_type=1 WHERE user_type <> 1";
MySqlCommand cmd = new MySqlCommand(updatedata, dbcon);
int numOfRowsChanged = cmd.ExecuteNonQuery();

Related

Copying data from one database to another - Out of Memory Exception

I have a task where i want to copy all data from one database to another database & skipping 2 tables. There are more than 200 tables.
I have table structure ready for my 2nd databas.
So as a solution i created a page & on a button click i have below code :-
DataSet ds = new DataSet();
string connectionString = "Data Source=COMP112\\MSSQLSERVER2014;Initial Catalog=HCMBL;Integrated Security=True;Persist Security Info=True";
SqlConnection con = new SqlConnection(connectionString);
//render table name from database
string sqlTable = "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' and TABLE_Schema='" + Session["SchemaName"].ToString() + "' and TABLE_NAME!='ENTRY' and TABLE_NAME!='OT' and TABLE_NAME!='BL_ENTRY' and TABLE_NAME!='BL_OT'";
con.Open();
SqlDataAdapter da = new SqlDataAdapter();
SqlCommand cmd = new SqlCommand(sqlTable, con);
cmd.CommandType = CommandType.Text;
da.SelectCommand = cmd;
da.Fill(ds);
con.Close();
//render connection string from WebConfig file
string strcon = ConfigurationManager.ConnectionStrings["SPSchema"].ConnectionString;
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
if (!(ds.Tables[0].Rows[i]["TABLE_NAME"].ToString().Contains("Asp")))
{
string deleteQuery = "Truncate table " + Session["SchemaName"].ToString() + "." + ds.Tables[0].Rows[i]["TABLE_NAME"];
con.Open();
SqlCommand cmdDelete = new SqlCommand(deleteQuery, con);
cmdDelete.ExecuteNonQuery();
con.Close();
DataSet dataSet = new DataSet();
SqlConnection conn = new SqlConnection(strcon);
conn.Open();
string selectData = "select * from " + Session["SchemaName"].ToString() + "." + ds.Tables[0].Rows[i]["TABLE_NAME"];
SqlCommand command = new SqlCommand(selectData, conn);
DataTable dataTable = new DataTable();
SqlDataAdapter dataAdapter = new SqlDataAdapter(selectData, conn);
dataAdapter.FillSchema(dataSet, SchemaType.Mapped);
dataAdapter.Fill(dataSet);
dataTable = dataSet.Tables[0];
conn.Close();
if (dataSet.Tables[0].Rows.Count > 0)
{
//Connect to second Database and Insert row/rows.
SqlConnection conn2 = new SqlConnection(connectionString);
conn2.Open();
SqlBulkCopy bulkCopy = new SqlBulkCopy(conn2);
bulkCopy.DestinationTableName = Session["SchemaName"].ToString() + "." + ds.Tables[0].Rows[i]["TABLE_NAME"].ToString();
bulkCopy.WriteToServer(dataTable);
conn2.Close();
}
}
}
As i run the above code after inserting data in less than 10 tables, it gives out of memory exception & program crashes.
How to handle this? I tried increasing the memory capacity of SQL Server but still same error.
Is there any other way to achieve the task?
What you are doing is very far from the best solution. You are using an ASP.NET MVC process to get all data of your entire database into memory, and then outputting it to another database. If your database is anything more than small and trivial, that will most definitely fill your process's alotted memory.
This type of task should never be done through the memory of a process, but rather using some form of Backup/Restore pattern.
You should look into SSIS projects and create an extract, transfer, and load (ETL) solution, which can be triggered from your ASP.NET MVC solution asynchronously.
An SSIS solution can be triggered from C# code in this way:
var app = new Application();
var package = app.LoadPackage("compiled-package.dtsx", null);
var results = package.Execute();
See this question for a little more information (not specifically about duplicating databases, but has information about triggering SSIS packages from code): How to execute an SSIS package from .NET?
Alternatively
You also have the option of running a query against both databases at once, however this requires some additional plumbing to be done. The user account of your ASP.NET MVC solution needs to have access to both databases. If your databases are hosted on different servers, you also need to link one server to the other: Create linked servers
To perform an insert directly from the output of a select, consider this:
string source = "NAME_OF_SOURCE_DATABASE";
string target = "NAME_OF_TARGET_DATABASE";
string schema = Session["SchemaName"].ToString();
string table = ds.Tables[0].Rows[i]["TABLE_NAME"];
// Uncomment this if you need to deal with autoincrement columns
/*string idInsQuery = $"SET IDENTITY_INSERT {target}.{schema}.{table} ON";
var idInsCommand = new SqlCommand(idInsQuery, conn);
idInsCommand.ExecuteNonQuery();*/
string insQuery = $"INSERT INTO {target}.{schema}.{table} SELECT * FROM {source}.{schema}.{table}";
var insCommand = new SqlCommand(insQuery, conn);
insCommand.ExecuteNonQuery();
// Uncomment this if you need to deal with autoincrement columns
/*string idInsQuery2 = $"SET IDENTITY_INSERT {target}.{schema}.{table} OFF";
var idInsCommand2 = new SqlCommand(idInsQuery2, conn);
idInsCommand2.ExecuteNonQuery();*/
This will only work if the table structures are identical. There might be problems with autoincrement ids or columns with default values, too.
This will copy data from a table in database 1 to a table in database 2
Insert into db2.dbo.table2 (col1,col2)
Select col1,col2 from db1.dbo.table1
Run this sql statement and the data will be copied without a round trip to your app.
Let me know if you find my approach is useful.
First of all, why you want to write down one whole application to do this job while SQL Server have inherited property to do it.
My approach would be configure an Linked Server and configure it which tables you want to copy and which one not.
https://learn.microsoft.com/en-us/sql/relational-databases/linked-servers/create-linked-servers-sql-server-database-engine
Secondly, You can just write down simple stored procedure and schedule that in your sql server to push into another server database as per your schedule. In this way you can control it in N number of ways. I mean about controlling any dependencies(Table level or Business level).
To do this in t-sql, you can use the following system stored procedures to schedule a daily job. This example schedules daily at 1:00 AM. See Microsoft help for details on syntax of the individual stored procedures and valid range of parameters.
DECLARE #job_name NVARCHAR(128), #description NVARCHAR(512), #owner_login_name NVARCHAR(128), #database_name NVARCHAR(128);
SET #job_name = N'Some Title';
SET #description = N'Periodically do something';
SET #owner_login_name = N'login';
SET #database_name = N'Database_Name';
-- Delete job if it already exists:
IF EXISTS(SELECT job_id FROM msdb.dbo.sysjobs WHERE (name = #job_name))
BEGIN
EXEC msdb.dbo.sp_delete_job
#job_name = #job_name;
END
-- Create the job:
EXEC msdb.dbo.sp_add_job
#job_name=#job_name,
#enabled=1,
#notify_level_eventlog=0,
#notify_level_email=2,
#notify_level_netsend=2,
#notify_level_page=2,
#delete_level=0,
#description=#description,
#category_name=N'[Uncategorized (Local)]',
#owner_login_name=#owner_login_name;
-- Add server:
EXEC msdb.dbo.sp_add_jobserver #job_name=#job_name;
-- Add step to execute SQL:
EXEC msdb.dbo.sp_add_jobstep
#job_name=#job_name,
#step_name=N'Execute SQL',
#step_id=1,
#cmdexec_success_code=0,
#on_success_action=1,
#on_fail_action=2,
#retry_attempts=0,
#retry_interval=0,
#os_run_priority=0,
#subsystem=N'TSQL',
#command=N'EXEC my_stored_procedure; -- OR ANY SQL STATEMENT',
#database_name=#database_name,
#flags=0;
-- Update job to set start step:
EXEC msdb.dbo.sp_update_job
#job_name=#job_name,
#enabled=1,
#start_step_id=1,
#notify_level_eventlog=0,
#notify_level_email=2,
#notify_level_netsend=2,
#notify_level_page=2,
#delete_level=0,
#description=#description,
#category_name=N'[Uncategorized (Local)]',
#owner_login_name=#owner_login_name,
#notify_email_operator_name=N'',
#notify_netsend_operator_name=N'',
#notify_page_operator_name=N'';
-- Schedule job:
EXEC msdb.dbo.sp_add_jobschedule
#job_name=#job_name,
#name=N'Daily',
#enabled=1,
#freq_type=4,
#freq_interval=1,
#freq_subday_type=1,
#freq_subday_interval=0,
#freq_relative_interval=0,
#freq_recurrence_factor=1,
#active_start_date=20170101, --YYYYMMDD
#active_end_date=99991231, --YYYYMMDD (this represents no end date)
#active_start_time=010000, --HHMMSS
#active_end_time=235959; --HHMMSS
Let me know in case you need more details on this.
Thanks,
Ayan

Cannot insert value via SqlDataAdapter

I am learning how to work with SQL in C#, and I got in troubles with using SqlDataAdapter. I have tried to use direct queries via SqlCommand class and everything works fine, but when I rewrote my code to use SqlDataAdapter I have no changes in my table. There is my code:
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ADO"]
.ConnectionString);
connection.Open();
SqlDataAdapter daUser = new SqlDataAdapter("SELECT * FROM Books", connection);
SqlCommand insert = new SqlCommand();
insert.Connection = connection;
insert.CommandText = "INSERT INTO Books (name, author) VALUES (#name, #author);";
SqlParameterCollection pc = insert.Parameters;
pc.Add("#name", SqlDbType.VarChar, 20, "test123");
pc.Add("#author", SqlDbType.VarChar, 20, "test322");
daUser.InsertCommand = insert;
DataSet ds = new DataSet();
daUser.Fill(ds, "Books");
daUser.Update(ds, "Books");
Table Books was created with this SQL query in SQL Server Management Studio:
CREATE TABLE Books
(
id int PRIMARY KEY IDENTITY(1,1),
name varchar(MAX) NOT NULL,
author varchar(MAX) NOT NULL
)
INSERT INTO Books(name, author)
VALUES('1984', 'George Orwell'), ('Fathers and sons', 'Dostoevski')
Looks like I am missing something to do, that why my code have no effect on table.
SqlDataAdapter.Update will call its InsertCommand only for the rows of datatable having RowState = DataRowState.Added.
This rowstate is automatically assigned to the datarows being added to rows collection using DataTable.Add method (until next call to AcceptChanges method). Also you can use DataRow.SetAdded method to force this state assignment.
Since you're not modifying/adding anything in you datatable after you've populated it with select command, it has nothing to insert.
Change your code to something like
daUser.Fill(ds, "Books");
var newBook = daUser.Tables[0].NewRow();
newBook["name"] = "New Book";
newBook["author"] = "Author Name";
daUser.Tables[0].Rows.Add(newBook);
daUser.Update(ds, "Books");
and in this case it should be new row added to the database table.
See MSDN for reference.
Just to clarify the previous answer, which is correct, you want to call ExecuteNonQuery() on the command not the dataAdapter.
SqlCommand insert = new SqlCommand();
insert.Connection = connection;
insert.CommandText = "INSERT INTO Books (name, author) VALUES (#name,
#author);";
SqlParameterCollection pc = insert.Parameters;
pc.Add("#name", SqlDbType.VarChar, 20, "test123");
pc.Add("#author",
SqlDbType.VarChar, 20, "test322");
// you do not need this line if you execute the insert on the command object.
// daUser.InsertCommand = insert;
//Add this line instead:
insert.ExecuteNonQuery();
Joey

DataAdapter.UpdateCommand not working c#?

I am using this code to update "SOME" columns in a table in my database. But everytime I try to do so an error is given.
No value given for one or more required parameters.
con.Open();
SlipDA = new OleDbDataAdapter();
string sqlUpdate = "Update tbl_Slip SET RaiseBasic=#RaiseBasic, OtherDed=#OtherDed, Arrears=#Arrears, Notes=#Notes WHERE SlipNo=#SlipNo";
SlipDA.UpdateCommand = new OleDbCommand(sqlUpdate, con);
SlipDA.UpdateCommand.Parameters.AddWithValue("#RaiseBasic", Convert.ToInt32(dRow[4].ToString()));
SlipDA.UpdateCommand.Parameters.AddWithValue("#OtherDed", Convert.ToInt32(dRow[5].ToString()));
SlipDA.UpdateCommand.Parameters.AddWithValue("#Arrears", Convert.ToInt32(dRow[7].ToString()));
SlipDA.UpdateCommand.Parameters.AddWithValue("#Notes", dRow[8].ToString());
SlipDA.UpdateCommand.Parameters.AddWithValue("#SlipNo", dRow[0].ToString());
SlipDA.UpdateCommand.ExecuteNonQuery();
con.Close();
The table contains 9 columns but I only want to update a few.
This Could be the problem :
The OLE DB .NET Provider does not support named parameters for passing
parameters to an SQL statement or a stored procedure called by an
OleDbCommand when CommandType is set to Text. In this case, the
question mark (?) placeholder must be used. For example: SELECT * FROM
Customers WHERE CustomerID = ?
source : this
so basically your query should be like this :
string sqlUpdate = "Update tbl_Slip SET RaiseBasic= ?, OtherDed= ?, Arrears= ?, Notes= ? WHERE SlipNo= ?";
try this
string sqlUpdate = "Update tbl_Slip SET RaiseBasic=#RaiseBasic, OtherDed=#OtherDed, Arrears=#Arrears, Notes=#Notes WHERE SlipNo=#SlipNo";
OleDbCommand UpdateCommand = new OleDbCommand(sqlUpdate, con);
UpdateCommand.Parameters.AddWithValue("#RaiseBasic", Convert.ToInt32(dRow[4].ToString()));
UpdateCommand.Parameters.AddWithValue("#OtherDed", Convert.ToInt32(dRow[5].ToString()));
UpdateCommand.Parameters.AddWithValue("#Arrears", Convert.ToInt32(dRow[7].ToString()));
UpdateCommand.Parameters.AddWithValue("#Notes", dRow[8].ToString());
UpdateCommand.Parameters.AddWithValue("#SlipNo", dRow[0].ToString());
con.Open();
UpdateCommand.ExecuteNonQuery();
con.Close();

OleDbDataAdapter Update To dbf [Free Table] -Syntax Error()

When I insert through the OleDbCommand with direct values no problem, it's working fine
OleDbCommand OleCmd1 = new OleDbCommand("Insert into My_Diary (sl_no,reminder) values("+a1+",'CHECK VALUE')", OleCon1);
OleCmd1->ExecuteNonQuery();
But when I like to update through parameter its showing "Syntax Error"....I can't identify my mistake...
string MyConStr = "Provider=VFPOLEDB.1; Data Source='C:\\For_Dbf'; Persist Security Info=False";
InsSavDiaryCmd = "Insert into My_Table1 (sl_no,reminder) values (#sl_no,#reminder) ";
VFPDAp=gcnew OleDbDataAdapter();
VFPDApMy_Table1InsertCommand = gcnew OleDbCommand(InsSavDiaryCmd, OleCon1);
WithInsVar = VFPDAp.InsertCommand.Parameters;
WithInsVar.Add("#sl_no", OleDbType.Integer, 10, "sl_no");
WithInsVar.Add("#reminder", OleDbType.Char, 250, "reminder");
OleCon1.ConnectionString = MyConStr;
OleCon1.Open();
OleDbTransaction Trans=OleCon1.BeginTransaction();
//VFPDAp.DeleteCommand.Transaction = Trans;
//VFPDAp.UpdateCommand.Transaction = Trans;
VFPDAp.InsertCommand.Transaction = Trans;
VFPDAp.Update(MyDataTbl);
Trans.Commit();
OleCon1.Close();
The OleDbCommand doesn't use named parameters. You need to change the insert statement so that it uses questions.
InsSavDiaryCmd = "Insert into My_Table1 (sl_no,reminder) values (?, ?) ";
You need to make sure that you have a parameter for each question mark and make sure that the parameters are inserted in order of their use in the insert statement.
** If you'd like to use name parameters... you can try using VfpClient which is a project that I'm working on to make data access a little nicer from .Net.

Cannot commit DataSet changes to database

I've written a small form that reads the data from a database table (SQL CE 3.5) and displays it in a DataGridView control. This works fine. I then modified it to make a change to the data before displaying it, which also seems to work fine with the exception that it doesn't seem to actually commit the changes to the database. The code is as follows:
using (SqlCeConnection conn = new SqlCeConnection(
Properties.Settings.Default.Form1ConnectionString
)) {
conn.Open();
using (SqlCeDataAdapter adapter = new SqlCeDataAdapter(
"SELECT * FROM People", conn
)) {
//Database update command
adapter.UpdateCommand = new SqlCeCommand(
"UPDATE People SET name = #name " +
"WHERE id = #id", conn);
adapter.UpdateCommand.Parameters.Add(
"#name", SqlDbType.NVarChar, 100, "name");
SqlCeParameter idParameter = adapter.UpdateCommand.Parameters.Add(
"#id", SqlDbType.Int);
idParameter.SourceColumn = "id";
idParameter.SourceVersion = DataRowVersion.Original;
//Create dataset
DataSet myDataSet = new DataSet("myDataSet");
DataTable people = myDataSet.Tables.Add("People");
//Edit dataset
adapter.Fill(myDataSet, "People");
people.Rows[0].SetField("name", "New Name!");
adapter.Update(people);
//Display the table contents in the form datagridview
this.dataGridView1.DataSource=people;
}
}
The form displays like so:
Looking at the table via Visual Studio's Server Explorer however, doesn't show any change to the table.
What am I doing wrong?
I found it. It took days but I found it.
Properties.Settings.Default.Form1ConnectionString is "Data Source=|DataDirectory|\Form1.sdf". The update works if I replace the automatically generated "|DataDirectory|" with the actual path. Oddly enough reading from the database works either way.
Shouldn't the update line be
adapter.Update(myDataSet, "People")
I would make sure the DataSet believes it's been changed. Invoke DataSet.HasChanges (returns bool) and DataSet.GetChanges, which returns a delta of the DataSet from the original.
Have you also tried this against Sql Server Express just to eliminate any issues with the CE data adapter?

Categories