c# database Select then insert. But the value is 0 - c#

I am trying to select then insert a datetime from Table 1 to Table 2. I have successfully insert the data. However, the datetime shown in Table 2 is 0000-00-00 00:00:00. Idk where is the error. Someone please help me with this problem. I am struggling with this. And is this the correct way to SELECT then insert ? (Select from Table 1 then INSERT into Table 2)
try
{
string myConnectionString;
myConnectionString= "server=localhost;uid=root;pwd=root;database=medicloud;SslMode=None;charset=utf8";
MySqlConnection connection = new MySqlConnection(myConnectionString);
MySqlCommand cmd = new MySqlCommand();
cmd.CommandType = CommandType.Text;
EncodingProvider ppp;
ppp = CodePagesEncodingProvider.Instance;
Encoding.RegisterProvider(ppp);
connection.Open();
string select = "Select time from assign where userId=#name";
cmd.Parameters.AddWithValue("#name", txtValue.Text);
cmd.CommandText = select;
cmd.Connection = connection;
MySqlDataReader selectAssign = cmd.ExecuteReader();
selectAssign.Read();
string assign = (selectAssign["time"].ToString());
selectAssign.Close();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "INSERT into bluetooth (userId,arm,armNumberDone,armNumber,comDate,assignDate,status) VALUES (#name, #stupid0, #stupid1, #stupid2, #stupid3, #stupid4, #stupid5)";
cmd.Parameters.AddWithValue("#stupid0", databaseLine);
cmd.Parameters.AddWithValue("#stupid1", counter);
cmd.Parameters.AddWithValue("#stupid2", databaseValue);
cmd.Parameters.AddWithValue("#stupid3", DateTime.Now);
cmd.Parameters.AddWithValue("#stupid4", assign);
cmd.Parameters.AddWithValue("#stupid5", complete);
cmd.Connection = connection;
cmd.ExecuteNonQuery();
connection.Close();
}
catch (MySqlException ex)
{
txtExercise.Text = ex.ToString();
}

Please try with this
try
{
string myConnectionString;
myConnectionString = "server=localhost;uid=root;pwd=root;database=medicloud;SslMode=None;charset=utf8";
MySqlConnection connection = new
MySqlConnection(myConnectionString);
MySqlCommand cmd = new MySqlCommand();
cmd.CommandType = CommandType.Text;
EncodingProvider ppp;
ppp = CodePagesEncodingProvider.Instance;
Encoding.RegisterProvider(ppp);
connection.Open();
string select = "Select time from assign where userId=#name";
cmd.Parameters.AddWithValue("#name", txtValue.Text);
cmd.CommandText = select;
cmd.Connection = connection;
MySqlDataReader selectAssign = cmd.ExecuteReader();
selectAssign.Read();
string assign = (selectAssign["time"].ToString());
selectAssign.Close();
DateTime assignDate = DateTime.Now;
DateTime.TryParseExact(assign, out assignDate);
cmd.CommandType = CommandType.Text;
cmd.CommandText = "INSERT into bluetooth
(userId,arm,armNumberDone,armNumber,comDate,assignDate,status) VALUES (#name,
#stupid0, #stupid1, #stupid2, #stupid3, #stupid4, #stupid5)";
cmd.Parameters.AddWithValue("#stupid0", databaseLine);
cmd.Parameters.AddWithValue("#stupid1", counter);
cmd.Parameters.AddWithValue("#stupid2", databaseValue);
cmd.Parameters.AddWithValue("#stupid3", DateTime.Now);
cmd.Parameters.AddWithValue("#stupid4", assignDate);
cmd.Parameters.AddWithValue("#stupid5", complete);
cmd.Connection = connection;
cmd.ExecuteNonQuery();
connection.Close();
}
catch (MySqlException ex)
{
txtExercise.Text = ex.ToString();
}
}

cmd.Parameters.AddWithValue("#stupid3", DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss"));
cmd.Parameters.AddWithValue("#stupid4", GetDateString(assign));
Have a method like this:
public static string GetDateString(string date)
{
DateTime theDate;
if (DateTime.TryParseExact(date, "dd/MM/yyyy HH:mm:ss",
CultureInfo.InvariantCulture, DateTimeStyles.None, out theDate))
{
// the string was successfully parsed into theDate
return theDate.ToString("dd/MM/yyyy HH:mm:ss");
}
else
{
// the parsing failed, return some sensible default value
return string.Empty;
}
}

You need to use .ExecuteReader() the use .Read() to move to each row in the result set. If you are sure the exactly one row will be returned, use .ExecuteScalar() instead. Research on the difference of both online. Below is an example using .ExecuteReader().
I also re-wrote to use using statements to simplify a bit but not deviate too much from your original code so you do not need to worry about closing and disposing resources since they inherit from IDisposable and will do that automatically once they exit the using block:
string assign = DateTime.Now.ToString();
string myConnectionString;
myConnectionString= "server=localhost;uid=root;pwd=root;database=medicloud;SslMode=None;charset=utf8";
string select = "Select time from assign where userId=#name";
using (MySqlConnection con = new MySqlConnection(myConnectionString))
{
using (MySqlCommand cmd = new MySqlCommand(select))
{
cmd.CommandType = CommandType.Text;
cmd.Connection = con;
cmd.Parameters.AddWithValue("#name", txtValue.Text);
using (MySqlDataReader cursor = cmd.ExecuteReader())
{
while (cursor.Read())
{
assign = cursor["time"];
}
}
}
string insert = "INSERT into bluetooth (userId,arm,armNumberDone,armNumber,comDate,assignDate,status) VALUES (#name, #stupid0, #stupid1, #stupid2, #stupid3, #stupid4, #stupid5)";
using (MySqlCommand cmd = new MySqlCommand(insert))
{
cmd.CommandType = CommandType.Text;
cmd.Connection = con;
cmd.Parameters.AddWithValue("#stupid0", databaseLine);
cmd.Parameters.AddWithValue("#stupid1", counter);
cmd.Parameters.AddWithValue("#stupid2", databaseValue);
cmd.Parameters.AddWithValue("#stupid3", DateTime.Now);
cmd.Parameters.AddWithValue("#stupid4", assign);
cmd.Parameters.AddWithValue("#stupid5", complete);
cmd.ExecuteNonQuery();
}
}

Related

Issue in update statement

I am writing the following lines of code to update the data in access database.
using (OleDbConnection con = new OleDbConnection())
{
con.ConnectionString = String.Format(Queries.dbConnection, databasePath);
con.Open();
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = con;
cmd.CommandText = "update tblusers set password = #password where userId = #userId;";
cmd.CommandType = System.Data.CommandType.Text;
cmd.Parameters.AddWithValue("#userId", authResult.UserId);
cmd.Parameters.AddWithValue("#password", newPassword);
cmd.ExecuteNonQuery();
}
}
When this line runs cmd.ExecuteNonQuery(); I got the following error:
Syntax error in UPDATE statement
Am I missing anything?
Update - 2
using (OleDbConnection con = new OleDbConnection())
{
con.ConnectionString = String.Format(Queries.dbConnection, databasePath);
con.Open();
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = con;
cmd.CommandText = "update tblusers set password = ? where userId = ?;";
cmd.CommandType = System.Data.CommandType.Text;
cmd.Parameters.Add("p1", OleDbType.VarChar, 100).Value = newPassword;
cmd.Parameters.Add("p2", OleDbType.Integer).Value = authResult.UserId;
cmd.ExecuteNonQuery();
}
}
First of all: MS Access / OleDB does not used named parameters - but positional parameters. So the order in which you specify the parameters is very much relevant!
Second: OleDB uses the ? as a parameter placeholder.
So try this code:
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = con;
cmd.CommandText = "update tblusers set [password] = ? where userId = ?;";
cmd.CommandType = System.Data.CommandType.Text;
// parameters - do *NOT* use "AddWithValue", and specify in the *correct order*!
// since the parameters are *positional*, the name provided is irrelevant
cmd.Parameters.Add("p1", OleDbType.VarChar, 50).Value = newPassword;
cmd.Parameters.Add("p2", OleDbType.Integer).Value = authResult.UserId;
cmd.ExecuteNonQuery();
}

if (counter == < database value >)

How do I make the value from my database as a int that I can use for my if else function ?
For example: In my database "armnumber = 3", how do I use it in my if else function ?
code
string myConnectionString;
myConnectionString = "server=localhost;uid=root;pwd=root;database=medicloud;SslMode=None;charset=utf8";
try
{
MySqlConnection connection = new MySqlConnection(myConnectionString);
MySqlCommand cmd = new MySqlCommand();
cmd.CommandType = CommandType.Text;
string sqlStr = "Select armnumber from assign where id=1";
cmd.CommandText = sqlStr;
cmd.Connection = connection;
connection.Open();
cmd.ExecuteNonQuery();
}
catch (MySqlException ex)
{
}
#endregion
if (counter == )
{
}
One option would be MySqlDataAdapter like this:
MySqlDataAdapter da = new MySqlDataAdapter {SelectCommand = cmd};
DataSet ds = new DataSet();
int armnumber = da.Fill(ds);
...
if (counter == armnumber)
Also you should always use parameterized queries to avoid SQL Injection:
string sqlStr = "Select armnumber from assign where id=#id";
cmd.Parameters.AddWithValue("#id", 1);
//Or better
cmd.Parameters.Add("#id", SqlDbType.Int).Value = 1;
You should replace this code
connection.Open();
MySqlDataReader reader = cmd.ExecuteReader();
reader.Read();
int databaseValue = int.Parse(reader["armnumber"].ToString());
connection.Close();
Few initial notes:
Continue operations after getting exception will not be a good practice, so I prefer the condition if (counter == xx ) inside the try block.
If the value of ID in the where clause is variable then make use of parameterization instead for concatenated queries.
Since you are fetching only a single field make use of ExecuteScalar instead for ExecuteNonQuery
You can make use of using als well for proper managing of connection and command objects.
So the code can be written as :
try
{
string sqlStr = "Select armnumber from assign where id=#id";
MySqlConnection connection = new MySqlConnection(myConnectionString);
MySqlCommand cmd = new MySqlCommand();
cmd.Parameters.AddWithValue("#id", 1);
cmd.CommandType = CommandType.Text;
cmd.CommandText = sqlStr;
cmd.Connection = connection;
connection.Open();
var result = cmd.ExecuteScalar();
int armnumber = result != null ? int.Parse(result.ToString()) : 0;
if (counter == armnumber)
{
// code here
}
}
catch (MySqlException ex)
{
}

MySqlCommand Object reference not set to an instance of an object

I want to update calorie_tracker table after burned value is calculated.Until cmd2 command it works.But while trying to cmd2 gives an error :Object reference not set to an instance of an object.How can I make this update in the same command(cmd) or is there any alternative?
string time = DateTime.Now.ToString("dd-MM-yyyy");
int burned = 0;
string s = (comboBox1.SelectedItem).ToString();
cnn.Open();
string cmdText = #"SELECT calorificValue
FROM myfitsecret.food
WHERE name=#name;
SELECT daily_gained
FROM myfitsecret.calorie_tracker
WHERE sportsman_id=#sportsman_id";
using (MySqlCommand cmd = new MySqlCommand(cmdText, cnn))
{
// Add both parameters to the same command
cmd.Parameters.Add("#name", MySqlDbType.String).Value = s;
cmd.Parameters.Add("#sportsman_id", MySqlDbType.String).Value = Login.userID;
using (MySqlDataReader reader = cmd.ExecuteReader())
{
// get sum from the first result
if (reader.Read()) burned += (Convert.ToInt32(reader[0])*int.Parse(textBox1.Text));
// if there is a second resultset, go there
if (reader.NextResult())
if (reader.Read())
burned += Convert.ToInt32(reader[0]);
}
cmd.Connection.Close();
MySqlCommand cmd2 = new MySqlCommand("update myfitsecret.calorie_tracker set daily_gained=#daily_gained where sportsman_id=#sportsman_id and Date=#Date");
cmd2.CommandType = CommandType.Text;
cmd2.Connection.Open();
cmd2.Parameters.AddWithValue("#daily_gained", burned);
cmd2.Parameters.AddWithValue("#Date", time);
cmd2.Parameters.Add("#sportsman_id", MySqlDbType.String).Value = Login.userID;
cmd2.ExecuteNonQuery();
You need to pass the connection to MySqlCommand before trying to open it like this:
cmd.Connection.Close();
MySqlCommand cmd2 = new MySqlCommand("update myfitsecret.calorie_tracker set daily_gained=#daily_gained where sportsman_id=#sportsman_id and Date=#Date",cnn);
cmd2.CommandType = CommandType.Text;
cmd2.Connection.Open();
I would also advise wrapping this command in a using statement as well.

C# SQL, Multiple Commands

I'm trying to write a method which should communicate with database, but I'm not sure if my approach is right.
public void dbWorkerLogin(int workerNumber) {
// Connection string stored in "conn"
if (!new SqlCommand("Some Command WHERE id=" +workernumber,conn).executeReader().HasRows)
{
new SqlCommand("exec STORED_PROCEDURE1 " + workerNumber, conn).ExecuteNonQuery();
new SqlCommand("exec STORED_PROCEDURE2 " + workerNumber, conn).ExecuteNonQuery();
}
else
{
new SqlCommand("exec STORED_PROCEDURE3 " + workerNumber,conn).ExecuteNonQuerry();
}
1) Is it ok to write it like this and start each SqlCommand with keyword new? Or should I do something like:
SqlCommand command = new SqlCommand(null, conn);
command = ...;
and then recycle the variable 'command' or this way?
using(SqlCommand cmd = new SqlCommand("COMMAND", conn);
2) Will my procedures work or should I use SqlCommand.Prepare() function that will covert my data into correct datatypes? eg. workerNumber is int, but in database it is stored as decimal.
using (SqlCommand cmd = new SqlCommand("STORED_PROCEDURE", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parametres.Add("#id", SqlDbType.Decimal).Value = workNumber;
cmd.Prepare();
cmd.ExecuteNonQuery();
}
Can you please somehow sum up what to use, what better not to? Unfortunately I can't test that first code because of limited access to DB so I'm not sure if it can be executed without errors or not.
Thank you for any help on this subject!
EDIT:
After a few hours I reach to this stage:
public int getWorkerNumber(string uniqueID)
{
using (conn = new SqlConnection(ConfigurationManager.ConnectionStrings["dbConnect"].ConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("SELECT number FROM worker WHERE workerID = #id",conn))
{
cmd.Parameters.Add("#id", SqlDbType.Decimal).Value = uniqueID;
using (SqlDataReader reader = cmd.ExecuteReader())
{
int answer;
while (reader.Read())
{
answer = (int)reader.GetDecimal(0);
}
return answer;
}
}
}
}
And this one:
public string dbLoginWorker(int workerNumber)
{
SqlCommand cmd;
SqlDataReader reader;
using (conn = new SqlConnection(ConfigurationManager.ConnectionStrings["dbConnect"].ConnectionString))
{
conn.Open();
cmd = new SqlCommand("SELECT column FROM table WHERE id= #workernumber", conn);
cmd.Parameters.Add("#workernumber", SqlDbType.Decimal).Value = workerNumber;
reader = cmd.ExecuteReader();
if (!reader.HasRows)
{
cmd = new SqlCommand("STORED_PROCEDURE1", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ID", SqlDbType.Decimal).Value = workerNumber;
cmd.Parameters.Add("#VARCHAR", SqlDbType.VarChar).Value = "text";
cmd.Prepare();
reader.Close();
cmd.ExecuteNonQuery();
cmd.Dispose();
reader.Dispose();
return "procedure 1 executed";
else
{
cmd = new SqlCommand("STORED_PROCEDURE2", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ID", SqlDbType.Decimal).Value = workerNumber;
cmd.Parameters.Add("#INT", SqlDbType.SmallInt).Value = 1;
cmd.Parameters.Add("#VARCHAR", SqlDbType.VarChar).Value = "text";
cmd.Prepare();
reader.Close();
cmd.ExecuteNonQuery();
cmd.Dispose();
reader.Dispose();
return "procedure 2 executed";
}
}
}
Both methods are functional (if I did no mistake in rewriting :) ). I'm not sure which of these methods (1st or 2nd) are better in terms of stability and if this approach is better and more ressistant to SQL Injection. Can someone comment on this subject? Thank you again for any help!
1) It is best to always use USING blocks when possible. This includes SqlConnection, SqlCommand, SqlReader and other objects that implement IDisposable. USING blocks automatically close and dispose of the objects, so you do not have to do so.
2) I believe that you are using the Prepare() method in the wrong place. Look at the following StackOverflow article for proper usage:
PrepareMethodInstructions.
3) in the dbLoginWorker() method, the first query is just used to determine if rows are found. Therefore, I suggest changing the SELECT command to SELECT TOP 1 column FROM table WHERE id= #workernumber so that the query is faster and more efficient.
4) I do not believe your commands are subject to SQL Injection attacks because they are fully parameterized. Good job on that one.
5) As a general thought, I suggest reading up on refactoring techniques. Your dbLoginWorker() method could be made more readable and maintainable, as well as self-documenting, if you created three additional methods, one for each SQL command, and named them something appropriate. You could also setup a method for creating a connection based on a connection name, and you would not have as much duplicate code. For example:
public static SqlConnection GetConnection(string connectionName)
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings[connectionName].ConnectionString);
conn.Open();
return conn;
}
public string dbLoginWorker(int workerNumber)
{
using (conn = GetConnection("dbConnect"))
{
if (CanFindWorkerNumber(conn, workerNumber))
ExecuteProcedure1(conn);
else
ExecuteProcedure2(conn);
}
}
public bool CanFindWorkerNumber (SqlConnection conn, int workerNumber)
{
bool success = false;
using (SqlCommand cmd = new SqlCommand("SELECT TOP 1 column FROM table WHERE id= #workernumber", conn))
{
cmd.Parameters.Add("#workernumber", SqlDbType.Decimal);
cmd.Prepare();
cmd.Parameters[0].Value = workerNumber;
success = cmd.ExecuteScalar() != null;
}
return success;
}
public void ExecuteProcedure1(SqlConnection conn)
{
using (SqlCommand cmd = new SqlCommand("STORED_PROCEDURE1", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ID", SqlDbType.Decimal);
cmd.Parameters.Add("#VARCHAR", SqlDbType.VarChar);
cmd.Prepare();
cmd.Parameters[0].Value = workerNumber;
cmd.Parameters[1].Value = "text";
cmd.ExecuteNonQuery();
}
}
public void ExecuteProcedure1(SqlConnection conn)
{
using (SqlCommand cmd = new SqlCommand("STORED_PROCEDURE1", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ID", SqlDbType.Decimal);
cmd.Parameters.Add("#INT", SqlDbType.SmallInt).Value);
cmd.Parameters.Add("#VARCHAR", SqlDbType.VarChar);
cmd.Prepare();
cmd.Parameters[0] = workerNumber;
cmd.Parameters[1] = 1;
cmd.Parameters[2] = "text";
cmd.ExecuteNonQuery();
}
}
You could actually do this in one SQL commend. Right now you are pulling back a result set only to see if it has rows or not, then executing different commands based on that. You should be able to do that in one command, disposing of it and the connection appropriately:
var sql =
#"
IF EXISTS(Some Command WHERE id=#workernumber)
BEGIN
exec STORED_PROCEDURE1 #workernumber;
exec STORED_PROCEDURE2 #workernumber;
END
ELSE
exec STORED_PROCEDURE3 #workernumber;
";
Note that you're not vulnerable to SQL injection because you're not dealing with strings, only integers.

What query syntax should I use for inserting records in an Oracle database?

I'm a beginner and trying to create a simple program in C# for inserting and updating records in an Oracle database. I have managed to successfully connect to the database but I'm getting an exception for my SQL statement which states that (?) symbol is not supported. Why am I getting this exception and how can I fix this?
My code is:
private void btnSave_Click(object sender, EventArgs e)
{
OracleConnection con = null;
try
{
con = new OracleConnection();
string constr = "Data source=XE; User ID=cloudester; Password=cloudester123;";
if (con.State != ConnectionState.Open)
{
try
{
con.ConnectionString = constr;
con.Open();
//MessageBox.Show("Successfull connection");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Exception caught");
}
}
if (con.State == ConnectionState.Open)
{
string str = "Insert into EMP_DETAIL(EmpId, Name, Age)";
str += "values (?,?,?)";
OracleCommand cmd = new OracleCommand();
cmd.CommandText = Text;
cmd.Connection = con;
cmd.Parameters.Add(new OracleParameter("EmpId", OracleDbType.Varchar2)).Value = txtEmpId;
cmd.Parameters.Add(new OracleParameter("Name", OracleDbType.Varchar2)).Value = txtName;
cmd.Parameters.Add(new OracleParameter("Age", OracleDbType.Int16)).Value = int.Parse(txtAge.Text);
cmd.ExecuteNonQuery();
}
}
catch { ... }
}
You need to use the named parameter for your command
string str = "Insert into EMP_DETAIL(EmpId, Name, Age) values (:EmpId, :Name, :Age)";
OracleCommand cmd = new OracleCommand();
cmd.CommandText = str; //cmd.CommandText = Text; not sure why did you use Text here
cmd.Connection = con;
cmd.Parameters.Add(new OracleParameter("EmpId", OracleDbType.Varchar2)).Value = txtEmpId;
cmd.Parameters.Add(new OracleParameter("Name", OracleDbType.Varchar2)).Value = txtName;
cmd.Parameters.Add(new OracleParameter("Age", OracleDbType.Int16)).Value = int.Parse(txtAge.Text);
cmd.ExecuteNonQuery();
As agent5566 said, and from OracleCommand.Parameters property;
When using named parameters in an SQL statement called by an
OracleCommand of CommandType.Text, you must precede the parameter name
with a colon (:)
Use them like;
using(var con = new OracleConnection(constr))
using(var cmd = con.CreateCommand())
{
cmd.CommandText = #"Insert into EMP_DETAIL(EmpId, Name, Age)
values (:EmpId, :Name, :Age)";
cmd.Parameters.Add(new OracleParameter("EmpId", OracleDbType.Varchar2)).Value = txtEmpId;
cmd.Parameters.Add(new OracleParameter("Name", OracleDbType.Varchar2)).Value = txtName;
cmd.Parameters.Add(new OracleParameter("Age", OracleDbType.Int16)).Value = int.Parse(txtAge.Text);
con.Open();
cmd.ExecuteNonQuery();
}
By the way, System.Data.OracleClient has been marked as deprecated in .NET 4 version. You might wanna use Oracle Data Provider for .NET instead.
As an alternative, DataDirect and DevArt also have their own oracle providers for .NET.

Categories