INSERT data from Textbox to Postgres SQL - c#

I just learn how to connect C# and PostgresSQL.
I want to INSERT data from tb1(Textbox) and tb2 to database. But I don't know how to code
My previous code is SELECT from database.
this is my code
private void button1_Click(object sender, EventArgs e)
{
bool blnfound = false;
NpgsqlConnection conn = new NpgsqlConnection("Server=127.0.0.1;Port=5432;User Id=postgres;Password=admin123;Database=Login");
conn.Open();
NpgsqlCommand cmd = new NpgsqlCommand("SELECT * FROM login WHERE name='" + tb1.Text + "' and password = '" + tb2.Text + "'",conn);
NpgsqlDataReader dr = cmd.ExecuteReader();
if (dr.Read())
{
blnfound = true;
Form2 f5 = new Form2();
f5.Show();
this.Hide();
}
if (blnfound == false)
{
MessageBox.Show("Name or password is incorrect", "Message Box", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
dr.Close();
conn.Close();
}
}
So please help me the code.

First off, you need to use the ExecuteNonQuery method rather than ExecuteReader since you're executing an INSERT rather than a SELECT statement. So, something like:
NpgsqlCommand cmd = new NpgsqlCommand("insert into table1 values(1, 1)", conn);
cmd.ExecuteNonQuery();
The ExecuteNonQuery method will also return the number of rows affected if that's important for you.
Second, you need to use SQL parameters rather than building an unsafe SQL string.
Use:
cmd.Parameters.Add(new NpgsqlParameter("name", tb1.Text));
cmd.Parameters.Add(new NpgsqlParameter("pw", tb2.Text));
To add a parameter to your query. You can now refer to it in your INSERT statement with :name or :pw, for example:
NpgsqlCommand cmd = new NpgsqlCommand("insert into login (Name, Password) values(:name, :pw)", conn);
cmd.ExecuteNonQuery();
Lastly, you might be interested in using an ORM rather than executing raw SQL statements. I'd check into the .NET Entity Framework or Castle Active Record, which is built on NHibernate. These libraries will allow you to query, update, create and delete data within your database without writing the actual SQL statements involved. It's a great way to get started, and will simply your code quite a bit!

Related

C# MySQL Inserting Same Data into 2 Different Tables

So I tried making a code for adding 2 same data within 2 different tables which is
"studentinfo" and "logindb"
I tried doing this
enter code heprivate void buttonRegisterStudent_Click(object sender, EventArgs e)
{
String connection = "server=localhost;user id=root;password=root;persistsecurityinfo=True;database=votingdb";
//Inserting Data
String insertDataInfo = #"INSERT INTO studentinfo (firstname,lastname,username,password,email) values
('"+this.textBoxFirstName.Text+"','"+this.textBoxLastName.Text+"','"+this.textBoxUsername.Text+
"','"+ this.textBoxPassword.Text + "','"+ this.textBoxEmail.Text + "')";
String insertDataLogin = #"INSERT INTO logindb (username,password) values ('"+this.textBoxUsername.Text+"','"
+this.textBoxPassword.Text+"')";
//Connection
MySqlConnection con = new MySqlConnection(connection);
MySqlCommand datainfo = new MySqlCommand(insertDataInfo,con);
MySqlCommand datalogin = new MySqlCommand(insertDataLogin, con);
MySqlDataReader datareaderinfo;
MySqlDataReader datareaderlogin;
try
{
con.Open();
datareaderinfo = datainfo.ExecuteReader();
datareaderlogin = datalogin.ExecuteReader();
MessageBox.Show("Student Register Successfully!");
}
catch (Exception ex)
{
MessageBox.Show("Failed to Register" + ex);
}
}
Resulting to Error which says there may only one mysqldatareader in the code. How can I add the same data to the different tables?
Don't use a datareader if you don't want to read data. Simple use the ExecuteNonQuery on your command:
datainfo.ExecuteNonQuery();
And don't forget to open en close your connection!
You don't need a data reader for insert statements, you should simply use ExecuteNonQuery.
Please note that your current queries are a security hazard as they are vulnerable to SQL Injection attacks.
Instead of concatenating user inputs as strings to create your SQL statements, use parameterized queries.
For more information, read How can prepared statements protect from SQL injection attacks?
An improved version of the main parts in your code is this:
var insertDataInfo = #"INSERT INTO studentinfo (firstname,lastname,username,password,email) values
(#firstName, #lastName, #userName, #passwordHash, #email)";
var insertDataLogin = #"INSERT INTO logindb (username,password) values (#userName, #passwordHash)";
var datainfo = new MySqlCommand(insertDataInfo,con);
datainfo.Parameters.Add("#firstName", DbType.VarChar).Value = this.textBoxFirstName.Text;
datainfo.Parameters.Add("#lastName", DbType.VarChar).Value = this.textBoxLastName.Text;
datainfo.Parameters.Add("#userName", DbType.VarChar).Value = this.textBoxUsername.Text;
datainfo.Parameters.Add("#passwordHash", DbType.VarChar).Value = this.textBoxPassword.Text;
datainfo.Parameters.Add("#email", DbType.VarChar).Value = this.textBoxEmail.Text;
var datalogin = new MySqlCommand(insertDataLogin, con);
datalogin.Parameters.Add("#userName", DbType.VarChar).Value = this.textBoxUsername.Text;
datalogin.Parameters.Add("#passwordHash", DbType.VarChar).Value = this.textBoxPassword.Text;
datainfo.ExecuteNonQuery();
datalogin.ExecuteNonQuery();
Also, you are storing passwords as plain text in your database.
That's a really big security hole. You should be storing salted hash values of your passwords instead - but that's getting a little too broad for this answer so I'll leave that part up for you to read and apply.

Execute DELETE only when the SELECT returns

I have a routine where I update the local database with other database data.
I only execute a DELETE and then an INSERT INTO tblX (SELECT * FROM tblY (tblY is a linked table)), as below.
The problem is that, in some cases the SELECT takes a long time after the DELETE and I´d like to diminish the possibility of the user to make a request to this table while it´s processing.
I´d like to know if there is some mechanism to execute the DELETE only after the return of the SELECT.
conn = new OleDbConnection(Conexao.getConexaoPainelGerencialLocal());
conn.Open();
OleDbCommand cmd = new OleDbCommand(" DELETE * FROM tblClienteContato; ", conn);
cmd.ExecuteNonQuery();
cmd = new OleDbCommand(" INSERT INTO tblClienteContato " +
" SELECT * FROM tblClienteContatoVinculada;", conn);
cmd.ExecuteNonQuery();
It sounds like what you need to do is wrap both of those commands in a transaction.
The cool thing about a transaction is that it either ALL WORKS or ALL FAILS, meaning that if something happens to stop the select statement, the database will not finalise the delete statement.
This looks like a really good example to work with:
https://msdn.microsoft.com/en-us/library/93ehy0z8(v=vs.110).aspx
Note that they have one command object, and replace the CommandText, rather than create a new object each time. This is probably important.
Try something like this:
conn = new OleDbConnection(Conexao.getConexaoPainelGerencialLocal());
OleDbCommand cmd = new OleDbCommand();
OleDbTransaction transaction = null;
try {
conn.Open();
transaction = conn.BeginTransaction(IsolationLevel.ReadCommitted);
cmd.Connection = conn;
cmd.Transaction = transaction;
cmd.CommandText = " DELETE * FROM tblClienteContato; ";
cmd.ExecuteNonQuery();
cmd.CommandText = " INSERT INTO tblClienteContato " +
" SELECT * FROM tblClienteContatoVinculada;";
cmd.ExecuteNonQuery();
// The data isn't _finally_ completed until this happens
transaction.Commit();
}
catch (Exception ex)
{
// Something has gone wrong.
// do whatever error messaging you do
Console.WriteLine(ex.Message);
try
{
// Attempt to roll back the transaction.
// this means your records won't be deleted
transaction.Rollback();
}
catch
{
// Do nothing here; transaction is not active.
}
}
You should look into BeginTransaction, Commit and rollback, here's an example:
_con.Open();
_con_trans = _con.BeginTransaction();
using(SqlCommand cmd = _con.CreateCommand())
{
cmd.CommandText = "delete from XXXXX";
cmd.CommandType = CommandType.Text;
cmd.Transaction = _con_trans;
cmd.ExecuteNonquery();
}
using(SqlCommand cmd = _con.CreateCommand())
{
cmd.CommandText = "insert into XXXX";
cmd.CommandType = CommandType.Text;
cmd.Transaction = _con_trans;
cmd.ExecuteNonquery();
}
_con_trans.Commit();
_con_trans = null;
_con.Close();
This way, everything is wrapped under a single transaction, so when the delete begins, the table will be locked for reading and writing.
Without knowing the schema of the table, it is hard to identify why the delete process is taking an extended amount of time.
An alternative to wrapping the commands within a transaction would be to simply delete the table itself rather than the data within it by using the DROP TABLE command. And then you can recreate the table utilizing the SELECT...INTO...FROM statement to recreate. A potential advantage to this is that the schemas will match identically, and any inherent conversions (eg decimal to int) will not need to be done.
using (conn = new OleDbConnection(Conexao.getConexaoPainelGerencialLocal())) {
conn.Open();
using (OleDbCommand cmd = new OleDbCommand()) {
cmd.CommandText = "DROP TABLE tblClienteContato; ";
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT * INTO tblClienteContato FROM tblClienteContatoVinculada;";
cmd.ExecuteNonQuery();
}
}
The following does not apply here (MS Access), but may to other SQL variants
Another option is to utilize the TRUNCATE command, which will delete everything in the table in one fell swoop. There is no logging of the individual rows and the indexes (if present) don't need to be recalculated on each and every line being deleted. The catch to this method is that this will not work within the transaction. If there is an Identity column the value will be reset as well. There are other potential cons to this but without knowing the design of the table I have no way of identifying them.
using (conn = new OleDbConnection(Conexao.getConexaoPainelGerencialLocal())) {
conn.Open();
using (OleDbCommand cmd = new OleDbCommand()) {
cmd.CommandText = "TRUNCATE TABLE tblClienteContato; ";
cmd.ExecuteNonQuery();
cmd.CommandText = " INSERT INTO tblClienteContato " +
" SELECT * FROM tblClienteContatoVinculada;";
cmd.ExecuteNonQuery();
}
}
As Greg commented, I created temporary tables to receive data from the external database and then I tranfer the data to the definitive tables, so that the probability of the users being impacted is very low.

Issues with Increment MS-SQL, C#

I am having an issue with the increment for the ID. The ID would increase by one every time I click insert, but the problem occurs when the ID 2, it would insert the values twice, if ID 3, it would insert the values three times, and so on.
There are couple of options that I have been trying. One is Max and the other one is finding the last inserted value and add one to the ID just.
I would appreciate if anyone can help me out with this. Thanks
public partial class LoginInfo : System.Web.UI.Page
{
static string myConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
private void GenerateID()
{
SqlConnection myConnection = new SqlConnection(myConnectionString);
string myQuery1 = "Select Count(S_ID) from Student_Name";
SqlCommand cmd = new SqlCommand(myQuery1, myConnection);
myConnection.Open();
int addOneS_ID_Table1 = Convert.ToInt32(cmd.ExecuteScalar());
myConnection.Close();
addOneS_ID_Table1++;
lblstdID.Text = addOneS_ID_Table1.ToString();
myConnection.Open();
cmd.CommandText = "Select Count(P_ID) from Student_Pass";
int addOneP_ID_Table2 = Convert.ToInt32(cmd.ExecuteScalar());
myConnection.Close();
addOneP_ID_Table2++;
lblstdPass.Text = addOneP_ID_Table2.ToString();
/*-----------------------------------------------------------------*/
//SqlConnection myConnection = new SqlConnection(myConnectionString);
//SqlCommand cmd = new SqlCommand("SELECT MAX(S_ID) as max_S_ID from Student_Name",myConnection);
//cmd.CommandType = CommandType.Text;
//myConnection.Open();
//lblstdID.Text = Convert.ToString(cmd.ExecuteScalar());
//cmd.CommandText = "SELECT MAX(P_ID) as max_P_ID FROM Student_Pass";
//lblstdPass.Text = Convert.ToString(cmd.ExecuteScalar());
//myConnection.Close();
}
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
GenerateID();
}
}
protected void btnInsert_Click(object sender, EventArgs e)
{
SqlConnection myConnection = new SqlConnection(myConnectionString);
string myQuery = "Insert into Student_Name(S_ID,STUDENT_NAME) VALUES" + "(#S_ID,#STUDENT_NAME)";
SqlCommand cmd = new SqlCommand(myQuery,myConnection);
cmd.Parameters.Add("#S_ID", SqlDbType.Int).Value = lblstdID.Text;
cmd.Parameters.Add("#STUDENT_NAME", SqlDbType.VarChar).Value = txtstdName.Text;
if(myConnection.State == ConnectionState.Closed)
{
myConnection.Open();
}
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
//Second Table
cmd.CommandText = "Insert into Student_Pass(P_ID,PASSWORD) VALUES" + "(#P_ID,#PASSWORD)";
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("#P_ID", SqlDbType.Int).Value = lblstdPass.Text;
cmd.Parameters.Add("#PASSWORD", SqlDbType.VarChar).Value = txtStdPass.Text;
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
myConnection.Close();
GenerateID();
lblResult.Text = "Successfully Saved";
GridView1.DataBind();
}
}
Problem is with your query since you are getting COUNT(S_ID) which is going to get you count of records doesn't necessarily will give exact ID number. You should rather try MAX(S_ID) or ORDER BY clause saying
Select MAX(S_ID) from Student_Name
(OR)
Select TOP 1 S_ID from Student_Name ORDER BY S_ID DESC;
But recommended, You should actually go with SQL Server ##IDENTITY or SCOPE_IDENTITY() to get the last inserted record ID (assuming that S_ID is an IDENTITY column)
It's highly recommended to not use max or top in order to determine the "next" identifier to use, simply because of the cost associated with it.
However, there are some other pitfalls to using max and top especially if there is a chance that nolock is used (which is a whole other conversation). I've seen a lot of web applications use max and has proven to be a performance killer.
Rahul is right, ##identity or scope_identity are good alternatives. However, I think this calls for using a native SQL Server sequence, which was introduced in SQL Server 2012. It was something that application developers have been waiting for and Microsoft finally delivered.
The issue with using ##identity or scope_identity is that you actually have to write rows to some table before you can even contemplate doing something.
This makes it a bit more costly and messier than what it may need to be. In the case of using a sequence, you can issue a new sequence number and then decide what to do and once you decide what to do you're still guaranteed that you're the only one with that sequence number.
You would create a sequence like this. You should check out the documentation as well.
create sequence dbo.StudentIdSeq
as int -- this can be any integer type
start with 1 -- you can start with any valid number in the int, even negative
increment by 1;
go
Then you issue new sequence numbers by doing this ...
select next value for StudentIdSeq;
It may still be good to create a stored procedure with an output parameter that you can call from C# (which is what I would do). In fact you may want to take it a step further, in the case that you have a bunch of sequences, and create a slick stored procedure that will get a new sequence based on the type that is being requested from the caller.

Letting the user add values into the database

I'm running a database in SQL2012 and using Visual Studio2012 C# to build a software that interacts with the database, and I've been trying to add a button that interacts with a textbox or something similar that lets the user add/edit rows in the database.
Code:
try
{
string conString = "Data Source=MIRANDA-PC;Initial Catalog=Futebol do Rosa;Integrated Security=True";
SqlConnection con = new SqlConnection(conString);
string selectSql = "Update Players$ SET Player Name='" + textBox3.Text + "' WHERE Player ID= 1";
SqlCommand cmd = new SqlCommand(selectSql, con);
con.Open();
cmd.ExecuteNonQuery();
MessageBox.Show("The values have been UPDATED");
}
catch{
MessageBox.Show("not so fast ***, error found in your ******** code");
}
Ignoring the safety issues (inline SQL is bad. Very bad.) Your update has some fundamental errors. Try:
string selectSql = "Update Players SET Players.Name='" + textBox3.Text +
"' WHERE Players.ID= 1";
Your table columns need to be associated to the table with a . and the table name has to be the same as the one you are updating. I am going on the assumption here that your table name is Players
The code in your link isn't even safe.
Your SqlConnction and SqlCommand will not dispose
The end user can use SQL Injection
Throw your SqlConnection and SqlCommand in an using statement.
using (SqlConnection con = new SqlConnection(constring))
{
using (SqlCommand cmd = new SqlCommand("your query here", con))
{
con.Open();
cmd.ExecuteNonQuery();
}
}
Add parameters to your SqlCommand to avoid SqlInjection
cmd.Parameters.AddWithValue("#param", value);
Create your own class for database interaction and don't put everything in one class or form.
If you let us know what the error is, we can help you more.
Also a good thing is to google your error first.

"incorrect syntax near keyword 'WHERE' " Exception

SqlCommand cmd1 = new SqlCommand("INSERT INTO Userinformation(Access)
VALUES("+nameAccess.Text+") WHERE User_ID='"+userIdaccess.Text+"'",con);
SqlDataReader dr = cmd1.ExecuteReader();
if (dr.Read())
{
MessageBox.Show("User Access Blocked");
}
dr.Close();
It is giving an exeption as below:
"incorrect syntax near keyword 'WHERE' "
Use parametrized queries to avoid SQL injection and also ensure to properly encode the query and also wrap your IDisposable resources in using statements to avoid leaking unmanaged handles. Also an INSERT SQL statement doesn't have a WHERE clause:
using (SqlCommand cmd1 = new SqlCommand("INSERT INTO Userinformation(Access) VALUES(#NameAccess)", con))
{
cmd1.Parameters.AddWithValue("#NameAccess", nameAccess.Text);
using (SqlDataReader dr = cmd1.ExecuteReader())
{
if (dr.Read())
{
MessageBox.Show("User Access Blocked");
}
}
}
Everytime you use the + operator when building a SQL query you are doing it wrong.
You can't do INSERT .. VALUES... WHERE, that's why. It's invalid syntax.
Insert Syntax : http://msdn.microsoft.com/en-us/library/ms174335.aspx
INSERT INTO doesn't have a WHERE clause. You can either do an UPDATE... WHERE your clause is met or insert both user info and user id as a new row.
try this code :
SqlCommand cmd1 = new SqlCommand("INSERT INTO Userinformation(Access)
VALUES('"+nameAccess.Text+"')",con);
SqlDataReader dr = cmd1.ExecuteReader();
if (dr.Read())
{
MessageBox.Show("User Access Blocked");
}
dr.Close();
Insert query have no where clause

Categories

Resources