I have a c# login forum that has two text-boxes
1.username
2.password
I am trying to check if the user exists in my Oracle database or not. If so, I want it to do something (like call another forum, etc...), but I'm getting an error msg that says I have a missing expression. Whats wrong with it?
private void button1_Click(object sender, EventArgs e)
{
isUserExist(textBox1.Text,textBox2.Text);
}
public bool isUserExist(string username,string password)
{
try
{
string connstring = "data source=test_db;user id=system;password=password;";
string statementcmd = "SELECT * FROM register_user Where UserName=#username";
OracleConnection conn = new OracleConnection(connstring);
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = statementcmd;
cmd.Parameters.Add("#username", username);
if (conn.State != ConnectionState.Open)
{
conn.Open();
OracleDataReader reader = cmd.ExecuteReader();
if (!reader.HasRows)
{ MessageBox.Show("User Name Not Found"); }
if (!password.Equals(reader["password"].ToString()))
MessageBox.Show("Incorrect Password");
reader.Close();
}
return true;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
return false;
}
}
You need to call the Read method on the DataReader before trying to access the properties.
if (reader.Read())
{
// Do stuff
}
Good luck!
1. you need to assign parameters before assigning commandstring to the CommandText.
2. you need to call Read() OracleDataReader object reader before accessing the records.
3. you should return true when true only when user is found.(in second if condition open curly braces is missing).
4. you can use using{} block for all IDisposable Implemented classes in your program so that their objects disposal will be taken care.(so you don't need to call Close() on Connection or Command objects)
Complete Solution:
public bool isUserExist(string username,string password)
{
bool status=false;
try
{
string connstring = "data source=test_db;user id=system;password=password;";
string statementcmd = "SELECT * FROM register_user Where [UserName]=#username";
using(OracleConnection conn = new OracleConnection(connstring))
{
using(OracleCommand cmd = new OracleCommand())
{
cmd.Connection = conn;
cmd.Parameters.Add("#username", username);//add parameters before assigning it to CommandText
cmd.CommandText = statementcmd;
if (conn.State != ConnectionState.Open)
{
conn.Open();
OracleDataReader reader = cmd.ExecuteReader();
if (!reader.Read())
{ MessageBox.Show("User Name Not Found"); }
if (!password.Equals(reader["password"].ToString()))
{
status=true;
MessageBox.Show("Incorrect Password");
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
status=false;
}
return status;
}
Related
I'm getting this error on phpMyAdmin
mysqli_connect(): (08004/1040): Too many connections
The only script that is using this DB:
public static bool checkIp(string ip)
{
Console.WriteLine("CHECKIP");
try
{
string sql = " SELECT * FROM `Ip tables` ";
MySqlConnection con = new MySqlConnection("host=hostname;user=username;password=password;database=database;");
MySqlCommand cmd = new MySqlCommand(sql, con);
con.Open();
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
if (ip == reader.GetString("Ip"))
{
Console.WriteLine("Benvenuto, " + reader.GetString("Name"));
con.Close();
return true;
}
}
con.Close();
return false;
}
catch(SqlException exp)
{
throw new InvalidOperationException("Error", exp);
}
}
Does this code close the connection correctly or something is wrong?
EDIT:
I added this block after the catch block
finally
{
if(con.State == System.Data.ConnectionState.Open)
{
con.Close();
}
}
Any better way to write the code? Would finaly block still run if return is executed?
You should put your query in a using statement like this:
string conString= "host=hostname;user=username;password=password;database=database;"
using (MySqlConnection con = new MySqlConnection(conString))
{
con.Open();
using (MySqlCommand com = con.CreateCommand())
{
com.CommandText = "SELECT * FROM `Ip tables`";
using (MySqlDataReader dr = com.ExecuteReader())
{
while (reader.Read())
{
if (ip == reader.GetString("Ip"))
{
Console.WriteLine("Benvenuto, " + reader.GetString("Name"));
con.Close();
return true;
}
}
}
}
}
This will automatically close the connection without having to state con.Close()
I am working on a windows form project with a sql database I want to write some data but I couldn't. (the code doesn't give any error however no data is written.
The code below is the place where I want to write the data:
public static string stringConnection = #"Data Source=(localdb)\MSSQLLocalDB; AttachDbFilename=|DataDirectory|\POS.mdf; Integrated Security=True";
try
{
mySql = string.Empty;
mySql += "INSERT INTO Journal (Date) VALUES (" + "'"+ caisse + "'"+")" ;
connection.exsql(mySql);
}
catch(Exception exx)
{
MessageBox.Show(exx.ToString());
}
and here is the connection.exsql method:
public static void exsql(string sql)
{
SqlConnection connection = new SqlConnection();
SqlDataAdapter adapter = default(SqlDataAdapter);
try
{
connection.ConnectionString = stringConnection;
connection.Open();
adapter = new SqlDataAdapter(sql, connection);
connection.Close();
//connection = null;
}
catch (Exception ex)
{
MessageBox.Show("Fatal sql error: " + ex.Message, "Sql Server connection failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
You want to use the sqlCommand and execute .ExecuteNonQuery() to do an INSERT or UPDATE.
More info here.
Also, use parameterization (an example is shown in the link above), otherwise, you open yourself up to SQL injection and your code will fail if your variable contains a single quote.
Less code
private bool exsql(string query)
{
using(var conn = new SqlConnection(ConnectionString.path))
{
conn.Open();
using (var command = new SqlCommand(query, conn))
return command.ExecuteNonQuery() == 0 ? false : true;
}
}
SqlConnection con;
SqlCommand cmd;
public bool exsql(string query)
{
try {
con = null;
con = new SqlConnection(ConnectionString.path);
cmd = new SqlCommand(query, con);
con.Open();
var rowEffected = cmd.ExecuteNonQuery();
con.Close();
if(rowEffected>0)
{
return true;
}
else
{
return false;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Exception occurred !",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
You can execute your query by ExecuteNonQuery() function
I am trying to make a login at the moment. I watched some videos and found a good way. Every user has an id, Username and Password. I want to get the id of the user who has just been logged in and save it in an Integer. I also tried it with an ExecuteReader but I get an Exception(MySql.Data.MySqlClient.MySqlException).
My current Code is:
try
{
if (sqlCon.State == ConnectionState.Closed)
{
sqlCon.Open();
}
string query = "SELECT COUNT(1) FROM Users_Table WHERE Username=#Username AND Password=#Password;";
MySqlCommand sqlCmd = new MySqlCommand(query, sqlCon);
sqlCmd.Parameters.AddWithValue("#Username", maintxtbox1.Text);
sqlCmd.Parameters.AddWithValue("#Password", Hashed_Password);
int count = Convert.ToInt32(sqlCmd.ExecuteScalar());
if (count == 1)
{
//Login correct
}
else
{
//Login incorrect
}
}
catch
{
//Exception
}
finally
{
sqlCon.Close();
}
The try with the ExecuteReader:
try
{
if (sqlCon.State == ConnectionState.Closed)
{
sqlCon.Open();
}
string query = "SELECT id,Username,Password FROM Users_Table WHERE Username=#Username AND Password=#Password;";
MySqlCommand sqlCmd = new MySqlCommand(query, sqlCon);
sqlCmd.Parameters.AddWithValue("#Username", maintxtbox1.Text);
sqlCmd.Parameters.AddWithValue("#Password", Hashed_Password);
MySqlDataReader datareader = sqlCmd.ExecuteReader();
if (datareader.HasRows)
{
MessageBox.Show("Test: " + datareader.GetString("id"));
}
else
{
//Login incorrect
}
}
catch
{
//Exception
}
finally
{
sqlCon.Close();
}
I hope somebody can help me. Thank you in advance.
Try and use the Read method:
if(datareader.Read()){
MessageBox.Show("Test: "+datareader.GetString(0));
}
EDIT:
To make good use and disposal of resources I recommend using the MySqlDataReader inside a using block, e.j.
using(MySqlDataReader reader = new sqlCmd.ExecuteReader()){
if(reader.Read()){
MessageBox.Show("Test: "+reader.GetString(0));
}
}
I found a solution to my Question by myself. I forgot the while(datareader.Read()) in the ìf(datareader.HasRows) query. Here is my working Code:
try
{
if (sqlCon.State == ConnectionState.Closed)
{
sqlCon.Open();
}
string query = "SELECT * FROM Users_Table WHERE username=#Username AND password=#Password;";
MySqlCommand sqlCmd = new MySqlCommand(query, sqlCon);
sqlCmd.Parameters.AddWithValue("#Username", maintxtbox1.Text);
sqlCmd.Parameters.AddWithValue("#Password", Hashed_Password);
MySqlDataReader datareader = sqlCmd.ExecuteReader();
if (datareader.HasRows)
{
while (datareader.Read())
{
UserID = datareader.GetInt32("id");
}
}
else
{
//Incorrect Password
}
}
catch
{
//Error
}
finally
{
sqlCon.Close();
}
So this method is supposed to get the ipaddress of the logged in user from a MySQL Database and print it to a textbox. However, I cant seem to get it right as the program just closes after I execute this method.
public void readIPAddress()
{
string username = GlobalData._sharedUserName;
String connString = System.Configuration.ConfigurationManager.ConnectionStrings["WebAppConnString"].ToString();
conn = new MySql.Data.MySqlClient.MySqlConnection(connString);
conn.Open();
queryStr = "";
queryStr = "SELECT ipaddress FROM webappdemo.userregistration WHERE username=?username";
cmd = new MySql.Data.MySqlClient.MySqlCommand(queryStr, conn);
cmd.Parameters.AddWithValue("?username", username);
cmd.ExecuteReader();
while (cmd.ExecuteReader().Read())
{
textBoxIPAddress.Text = reader["ipaddress"].ToString();
}
conn.Close();
}
If anyone could point out where I went wrong, I greatly appreciate your help!
Edit: After using try and catch I get this:
MySql.Data.MySqlClient.MySqlException (0x80004005): There is already an open DataReader associated with this Connection which must be closed first.
at MySql.Data.MySqlClient.ExceptionInterceptor.Throw(Exception exception)
at MySql.Data.MySqlClient.MySqlConnection.Throw(Exception ex)
at MySql.Data.MySqlClient.MySqlCommand.CheckState()
at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader()
at ConnectToDataBase.Form2.readIPAddress() in C:\Users\ee\Dropbox\ConnectToDataBase\ConnectToDataBase\Form2.cs:line 95
Quick Fix:
You are executing the command two times, using ExecuteReader that's why you are getting such exception. If you execute the code like this means your code will works fine:
string queryStr = "SELECT ipaddress FROM webappdemo.userregistration WHERE username=#username";
using (MySqlConnection conn = new MySqlConnection(connString))
{
conn.Open();
using (MySqlCommand cmd = new MySqlCommand(queryStr, conn))
{
cmd.Parameters.AddWithValue("#username", username);
var reader = cmd.ExecuteReader();
while (reader.Read())
{
textBoxIPAddress.Text = reader["ipaddress"].ToString();
}
}
}
Smart Fix:
Here you are fetching a single value from the database in such situations you need not to use reader at all. you can simply access those value by using ExecuteScalar() method, which will give you the required object. if so You can use the following code:
using(MySqlConnection conn = new MySqlConnection(connString))
{
using(MySqlCommand cmd= new MySqlCommand(query, conn))
{
cmd.Parameters.Add("#username", username);
conn.Open();
object ipAddress= cmd.ExecuteScalar();
if (ipAddress!= null)
textBoxIPAddress.Text = ipAddress.ToString();
else
textBoxIPAddress.Text = "No data found";
}
}
Hope that you wont forget to add MySql.Data.MySqlClient; to the using section
you are executing reader two times by calling ExecuteReader(), why you need Reader here, if you only need one value from database. use ExecuteScalar that will return first value of the first record from the result. Sample code:
try
{
string query = "SELECT ipaddress FROM webappdemo.userregistration WHERE username = #username";
string connString =ConfigurationManager.ConnectionStrings["WebAppConnString"].ToString();
using(MySqlConnection connection = new MySqlConnection(connString))
{
using(MySqlCommand command = new MySqlCommand(query, connection))
{
command.Parameters.Add("#username", username);
connection.Open();
object ip= command.ExecuteScalar();
if (ip != null) {
textBoxIPAddress.Text = ip.ToString();
}
}
}
}
catch(MySqlException ex)
{
// do something with the exception
}
Problem:
cmd.ExecuteReader(); //Executing reader and not assigning to anything
while (cmd.ExecuteReader().Read()) //Executing reader again and not assigning to anything again
{
//There is nothing assigned to reader.
textBoxIPAddress.Text = reader["ipaddress"].ToString();
}
Quick Solution:
//assuming reader is defined
reader = cmd.ExecuteReader();
while (reader.Read()) //read from the reader
{
textBoxIPAddress.Text = reader["ipaddress"].ToString();
}
Alternative Solutions using MySql.Data.MySqlClient.MySqlHelper:
try {
object ip = MySqlHelper.ExecuteScalar(connString, query, new MySqlParameter[] {
new MySqlParameter("?username", username)
}));
if (ip != null) {
textBoxIPAddress.Text = ip.ToString();
}
} catch (Exception ex) {
// do something with the exceptio
}
If you insist on using reader:
//assuming reader is defined
reader = MySqlHelper.ExecuteReader(connString, query, new MySqlParameter[] {
new MySqlParameter("?username", username)
}));
while (reader.Read()) //read from the reader
{
textBoxIPAddress.Text = reader["ipaddress"].ToString();
}
Note: the above code is just typed in here and may contain syntax errors. take this a a guideline.
I try to call function to select data from database,coz it will more efficient and i don't like to open connection and execute reader every time,have any solution can do like that?
this is my first method to select data from database,but will hit sql injection problem
protected void Button1_Click(object sender, EventArgs e)
{
Class1 myClass = new Class1();
lblAns.Text = myClass.getdata("Table1", "Student", "Student = '" + TextBox1.Text + "'");
}
public string getdata(string table,string field,string condition)
{
SqlDataReader rdr;
SqlConnection conn = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database1.mdf;Integrated Security=True;User Instance=True");
string sql = "select " + field + " from " + table + " where " + condition;
try
{
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
return "true";
}
}
catch (System.Data.SqlClient.SqlException ex)
{
string msg = "Insert Error:";
msg += ex.Message;
}
finally
{
conn.Close();
}
return "false";
}
this is my second method but will hit error (ExecuteReader requires an open and available Connection. The connection's current state is closed.) at line (rdr = cmd.ExecuteReader();)
public string getdata(SqlCommand command,SqlConnection conn)
{
SqlDataReader rdr;
try
{
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd = command;
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
return "true";
}
}
catch (System.Data.SqlClient.SqlException ex)
{
string msg = "Select Error:";
msg += ex.Message;
}
finally
{
conn.Close();
}
return "false";
}
public SqlConnection conn()
{
SqlConnection conn = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database1.mdf;Integrated Security=True;User Instance=True");
return conn;
}
protected void Button1_Click(object sender, EventArgs e)
{
Class1 myClass = new Class1();
string strSql;
strSql = "Select student from Table1 where student=#stu";
SqlCommand command = new SqlCommand(strSql, myClass.conn());
command.Parameters.AddWithValue("#stu", TextBox1.Text);
myClass.getdata(command, myClass.conn());
}
have solution can use 1st method but will not hit the sql injection problem?
Use ALWAYS the second solution. The only way to avoid Sql Injection is through the use of parameterized queries.
Also fix the error on the second example. You don't associate the connection to the command, also it is a bad practice to keep a global object for the connection. In ADO.NET exist the concept of Connection Pooling that avoid the costly open/close of the connection while maintaining a safe Handling of these objects
public string getdata(SqlCommand command)
{
// Using statement to be sure to dispose the connection
using(SqlConnection conn = new SqlConnection(connectionString))
{
try
{
conn.Open();
cmd.Connection = conn;
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
return "true";
}
}
catch (System.Data.SqlClient.SqlException ex)
{
string msg = "Select Error:";
msg += ex.Message;
return msg;
}
}
return "false";
}