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
Related
This question already has answers here:
What are good ways to prevent SQL injection? [duplicate]
(4 answers)
Closed 3 years ago.
I am currently building my first web app from scratch and trying to figure out the communication of C# and SQLDatabases, I've been trying to enter custom data into a table.
This code for some reason works perfectly fine, and it successfully adds "Id = 3" in a new row:
sql = " INSERT INTO dbo.AspNetUsers (Id) VALUES (3)";
SqlCommand command = new SqlCommand(sql, cnn);
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.InsertCommand = new SqlCommand(sql, cnn);
adapter.InsertCommand.ExecuteNonQuery();
But this one does not, and the only difference is that it adds another item in a different column, as opposed to the previous one which it only adds the "Id":
sql = " INSERT INTO dbo.AspNetUsers (Id, UserName) VALUES (3, testName)";
SqlCommand command = new SqlCommand(sql, cnn);
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.InsertCommand = new SqlCommand(sql, cnn);
adapter.InsertCommand.ExecuteNonQuery();
Lastly, another problem I have, I am unable to use either ExecuteReader() and ExecuteScalar() to read data from tables created by me as opposed the ones set up by the Framework auth system.
Thanks in advance.
This code addresses both issues:
the value of UserName is passed as a SQL parameter, which is recommended for string values to avoid SQL injection and other possible problems,
the SQL command is executed with ExecuteNonQuery, the correct way of calling SQL commands that do not return any result
SqlCommand cmd = new SqlCommand();
string sql = " INSERT INTO dbo.AspNetUsers (Id, UserName) VALUES (3, #testName)";
cmd.Parameters.AddWithValue("#testName", "testName");
cmd.Connection = con;
cmd.CommandText = sql;
con.Open();
cmd.ExecuteNonQuery();
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();
I have procedure like this?
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `check_user`(in username varchar(100), in pass varchar(5000))
BEGIN
select * from users where email=username and password = pass;
END$$
DELIMITER ;
So i call procedure like this.
MySqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "get_user";
cmd.Parameters.AddWithValue("#username", un);
cmd.Parameters.AddWithValue("#pass", Security.Encrypt(pass));
int result = cmd.ExecuteNonQuery();
it shows result as 0. Because not any row affected. In this case can't identify user is exist or not. User exist or not result always 0. So how can i get user is exist or not ?
ExecuteNonQuery should not be used in SELECT statements.
ExecuteNonQuery method is to be used to perform 'Data Manipulation Language'. This is used only in INSERT, DELETE and UPDATE.
ExecuteScalar method will return a single value in the first row, first column from a SELECT statement. So changing your query with SELECT COUNT(*).. can be use.
The ExecuteReader Method will return the result set of a SELECT. This method is to be used when you're querying for a bunch of results, such as rows from a table etc.
Change your query with this:
SELECT COUNT(*) FROM users WHERE email=username AND password = pass;
And use ExecuteScalar() and you are ready to go.
Or you can use DataAdapter Fill like this:
MySqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "get_user";
cmd.Parameters.AddWithValue("#username", un);
cmd.Parameters.AddWithValue("#pass", Security.Encrypt(pass));
DataTable data = new DataTable();
using (MySqlDataAdapter da = new MySqlDataAdapter(cmd))
{
da.Fill(data);
}
if (data.Rows.Count > 0)
result = Convert.ToInt32(data.Rows[0][0].ToString());
Read more here.
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.
I create a table in SQL Server Management Studio with this code:
CREATE TABLE contact(
ID INT IDENTITY NOT NULL,
FIRSTNAME VARCHAR(100),
LASTNAME VARCHAR(100)
)
and in C# I used this code:
SqlConnection sc = new SqlConnection("Data Source=.\\SQLSERVER; Initial Catalog=BOSS; Integrated Security=TRUE");
SqlDataAdapter sd = new SqlDataAdapter();
sd.InsertCommand = new SqlCommand("INSERT INTO contact VALUES(#ID, #FIRSTNAME, #LASTNAME)");
sd.InsertCommand.Parameters.Add("#ID", SqlDbType.Int).Value = textBox1.Text;
sd.InsertCommand.Parameters.Add("#FIRSTNAME", SqlDbType.VarChar).Value = textBox2.Text;
sd.InsertCommand.Parameters.Add("#LASTNAME", SqlDbType.VarChar).Value = textBox3.Text;
sc.Open();
sd.InsertCommand.ExecuteNonQuery();
sc.Close();
but when I add the values to the database I get the error:
"ExecuteNonQuery: Connection property has not been initialized"
and I fixed it by adding sc to my first insertcommand, but when I run the program I got another error :
An explicit value for the identity column in table 'contact' can only
be specified when a column list is used and IDENTITY_INSERT is ON.
Do it this way:
using(SqlConnection sc = new SqlConnection("Data Source=.\\SQLSERVER; Initial Catalog=BOSS; Integrated Security=TRUE"))
{
using(SqlCommand command = new SqlCommand())
{
command.CommandText = "INSERT INTO contact (FirstName, LastName) VALUES(#FIRSTNAME , #LASTNAME");
command.CommandType = CommandType.Text;
command.Connection = sc;
command.Parameters.AddWithValue("#FIRSTNAME", textBox2.Text);
command.Parameters.AddWithValue("#LASTNAME", textBox3.Text);
sc.Open();
command.ExecuteNonQuery();
}
}
Important things to note:
1) Set your table up to have the Id column as an identity column and set autoincrement to true. This will automatically generate a numeric id when you insert
2) You are trying to insert into an identity column - you can't actually do this unless you enable identity inserts. I wouldn't bother - just use an autoincrement column and let the database control the id generation step.
You can generate your table this way:
CREATE TABLE Contact
(
Id int PRIMARY KEY IDENTITY,
FirstName varchar(100),
LastName varchar(100)
)
to get an autoincrementing primary key.
3) You don't need the SqlDataAdapter.
You need to pass the connection you intend to use to the SqlCommand
InsertCommand = new SqlCommand("INSERT INTO contact VALUES(#ID , #FIRSTNAME , #LASTNAME)", sc);
You need to dispose of your Connection and command as well. The standard pattern for doing this is:
using (SqlConnection conn = new SqlConnection("Data Source=.\\SQLSERVER; Initial Catalog=BOSS; Integrated Security=TRUE")){
conn.Open();
using (SqlCommand command = new SqlCommand(sqlString, conn)){
//stuff...
command.ExecuteNonQuery();
}
}
There's no relation between SqlConnection and SqlDataAdapter.
In fact, you don't need SqlDataAdapter. You only need SqlConnection and SqlCommand, for which you must use the constructor overload that accepts a connection as well.
Since ID is an INT IDENTITY field, you shouldn't (and can't) insert values into it. But if you use your "generic" INSERT statement without explicitly specifying which columns to insert values into, your INSERT statement will attempt to insert data into all columns - including ID, which you cannot insert anything into.
The solution (which I recommend for use always) is to explicitly define which columns to insert values into:
INSERT INTO dbo.contact(FirstName, LastName) VALUES(#FIRSTNAME, #LASTNAME)
This also works if you need to change your table and add another column - your original statement will fail, since the table suddenly now would have four columns, but your statement would only provide three values. If you explicitly define which columns you want to provide values for, your statement is more robust and works better.
So your complete code should look like this:
using(SqlConnection sc = new SqlConnection("Data Source=.\\SQLSERVER; Initial Catalog=BOSS; Integrated Security=TRUE"))
using(SqlCommand cmdInsert = new SqlCommand("INSERT INTO dbo.Contact(FirstName, LastName) VALUES(#FIRSTNAME, #LASTNAME)", sc))
{
cmdInsert.Parameters.Add("#FIRSTNAME", SqlDbType.VarChar, 100).Value = textBox2.Text;
cmdInsert.Parameters.Add("#LASTNAME", SqlDbType.VarChar, 100).Value = textBox3.Text;
sc.Open();
cmdInsert.ExecuteNonQuery();
sc.Close();
}
You need sd.InsertCommand = new SqlCommand("INSERT INTO contact VALUES(#ID , #FIRSTNAME , #LASTNAME)", sc);
You can do either ways:
a. Set you connection object to the adapter's insertcommand connection:
sd.InsertCommand.Connection = sc;
Or
b. Pass your connection object while initializing insert command as below:
sd.InsertCommand =
new SqlCommand("INSERT INTO contact VALUES(#ID, #FIRSTNAME, #LASTNAME)", sc);