I have some Steam trading bots and i am trying to insert to a database whether a trade was successful or not (true). You can see my code below. I get absolutely no errors and the regular trades, functions and console logging works fine. I check the db for content and nothing is there.
I am new to SQL in C#. Is someone able to tell me whats wrong with my code?
public override void OnTradeAccept()
{
bool didSomething = false;
if ((Validate()) || (IsAdmin && mode == ADMINMODE) || ChooseDonate)
{
bool success = Trade.AcceptTrade();
if (success) //makes sure trades were successfull
{
//I removed con details
string constr = "server=;database=;userid=;password=;";
MySqlConnection con = null;
try
{
con = new MySqlConnection(constr);
con.Open(); //open the connection
string insertTrue = "INSERT INTO trade_success(state) VALUES ('true')";
MySqlCommand command = new MySqlCommand(insertTrue, con);
command.ExecuteNonQuery();
}
catch (MySqlException err) //We will capture and display any MySql errors that will occur
{
Console.WriteLine("Error: " + err.ToString());
}
finally
{
if (con != null)
{
con.Close();
}
}
Log.Success("Trade was successful!");
//sendChatMessage(tradeSuccessMessage1);
sendChatMessage(tradeSuccessMessage2);
Bot.SteamFriends.SetPersonaState(EPersonaState.LookingToTrade);
}
else
{
Log.Warn("Trade might have failed.");
Bot.SteamFriends.SetPersonaState(EPersonaState.LookingToTrade);
}
}
}
Related
I'm wanting to make a small and simple mobile app for a school project, I know connecting to a db from a phone is not good for security reasons but basically only I will touch it.
So to connect my Xamarin app to Mysql I downloaded the extension MysqlConnector (https://www.nuget.org/packages/MySqlConnector/2.1.8?_src=template)
Everything seemed to work at first, but now I think that there is a problem in their library that is not compatible with Xamarin:
I seem to always get a nullreference exception at the second query at line
reader = cmd.ExecuteReader();. I don't know why, nothing is null, I've printed everything.
(I've put a comment on the line where it happens) I seriously doubt it is a problem in their library since they have 37.2M downloads in total. But maybe it is just a compatability conflict, but that makes it odd that the first query works then.
Here is all my current code:
using PuppyChinoBestelling.Views;
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
using MySqlConnector;
using System.Threading.Tasks;
namespace PuppyChinoBestelling.ViewModels
{
public class LoginViewModel : BaseViewModel
{
public Command LoginCommand { get; }
public string Mail { get; set; }
public string Pass { get; set; }
public LoginViewModel()
{
Pass = string.Empty;
Mail = string.Empty;
LoginCommand = new Command(OnLoginClicked);
}
private async void OnLoginClicked(object obj)
{
MySqlConnection conn = new MySqlConnection("private");
try
{
conn.Open();
Console.WriteLine("Conn opened!");
}
catch(Exception ex)
{
Console.WriteLine("Error " + ex.Message);
}
string sql = #"SELECT * FROM users WHERE email = #email;";
var cmd = conn.CreateCommand();
cmd.CommandText = sql;
cmd.Parameters.AddWithValue("#email", Mail);
var reader = cmd.ExecuteReader();
if (reader.HasRows)
{
sql = #"SELECT * FROM users WHERE email = #email;";
cmd = conn.CreateCommand();
cmd.Parameters.Clear();
cmd.CommandText = sql;
cmd.Parameters.AddWithValue("#email", Mail);
reader = cmd.ExecuteReader(); //null reference happening here idk why
string pwdHashed = reader.GetString(5);
bool validPwd = BCrypt.Net.BCrypt.Verify(Pass, pwdHashed);
conn.Close();
if (validPwd)
{
await Shell.Current.GoToAsync($"//{nameof(AboutPage)}");
}
else
{
Console.WriteLine("Foute logingegevens!");
}
}
else
{
Console.WriteLine("Je bestaat niet!");
}
}
}
}
Thanks in advance!
It's hard to say for certain, but it's likely the issue is because you are not closing the reader and command, and you can't have multiple commands on the same connection.
Also, you need to advance the reader using reader.Read.
In any case there is no need to run the command twice in the first place. You already had all the information on the first run.
You also need to dispose everything with using. This automatically closes the connection.
Don't SELECT *, just select the columns you need.
Ideally, you would calculate the hash for the given password, and send it to the database server to check, rather than pulling out the real password hash from the database (could be a security risk).
Don't store hashes as strings. Instead store them as binary with the varbinary data type, and cast to byte[] on the C# side.
Unclear why you are handling errors only for opening the connection, not for executing the command.
private async void OnLoginClicked(object obj)
{
const string sql = #"
SELECT Pass
FROM users
WHERE email = #email;
";
using (var conn = new MySqlConnection("private"))
using (var cmd = new MySqlCommand(sql, conn))
{
try
{
conn.Open();
Console.WriteLine("Conn opened!");
}
catch(Exception ex)
{
Console.WriteLine("Error " + ex.Message);
return; // no point continuing
}
cmd.Parameters.AddWithValue("#email", Mail);
using (var reader = cmd.ExecuteReader())
{
if (!reader.Read())
{
Console.WriteLine("Je bestaat niet!");
return; // no point continuing
}
string pwdHashed = (string)reader["Pass"];
conn.Close();
bool validPwd = BCrypt.Net.BCrypt.Verify(Pass, pwdHashed);
if (validPwd)
{
await Shell.Current.GoToAsync($"//{nameof(AboutPage)}");
}
else
{
Console.WriteLine("Foute logingegevens!");
}
}
}
}
An alternative method is to remove the reader altogether and use ExecuteScalar
private async void OnLoginClicked(object obj)
{
const string sql = #"
SELECT Pass
FROM users
WHERE email = #email;
";
using (var conn = new MySqlConnection("private"))
using (var cmd = new MySqlCommand(sql, conn))
{
try
{
conn.Open();
Console.WriteLine("Conn opened!");
}
catch(Exception ex)
{
Console.WriteLine("Error " + ex.Message);
return; // no point continuing
}
cmd.Parameters.AddWithValue("#email", Mail);
string pwdHashed = cmd.ExecuteScalar() as string;
conn.Close();
if (pwdHashed is null)
{
Console.WriteLine("Je bestaat niet!");
return; // no point continuing
}
bool validPwd = BCrypt.Net.BCrypt.Verify(Pass, pwdHashed);
if (validPwd)
{
await Shell.Current.GoToAsync($"//{nameof(AboutPage)}");
}
else
{
Console.WriteLine("Foute logingegevens!");
}
}
}
I have a code in which I am trying to insert the records. All the records are inserted but with duplicates. I want to stop duplication of same record.
public int SaveReadingsInCIS(Reading pReading)
{
SqlConnection con = new SqlConnection("Data Source=RND-FAISAL;Initial Catalog=hesco;Integrated Security=True;MultipleActiveResultSets=True;");
int result = -1;
string dt = pReading.XTimeStamp.Replace("T"," ");
string fdt = dt.Remove(dt.Length-6);
if (con.State != ConnectionState.Open)
{
con.Open();
}
SqlCommand insert_cmd = new SqlCommand("INSERT INTO [dbo].[billing]([unique_id],[ref_no],[msn],"+
"[kWh1],[kVarh1],[kWh2],[kVarh2],[datetime])VALUES(#uniqueid,#refno,#msn,#kwh1,#kvarh1,#kwh2,#kvarh2,#datetime)",con);
insert_cmd.CommandType = CommandType.Text;
insert_cmd.Parameters.AddWithValue("#uniqueid",pReading.App_no);
insert_cmd.Parameters.AddWithValue("#refno",pReading.Ref_no);
insert_cmd.Parameters.AddWithValue("#msn",pReading.Serial_no);
insert_cmd.Parameters.AddWithValue("#kwh1",pReading.KWH1);
insert_cmd.Parameters.AddWithValue("#kvarh1",pReading.KVARH1);
insert_cmd.Parameters.AddWithValue("#kwh2",pReading.KWH2);
insert_cmd.Parameters.AddWithValue("#kvarh2",pReading.KVARH2);
insert_cmd.Parameters.AddWithValue("#datetime", fdt.ToString());
try
{
result = insert_cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
result = ex.HResult;
}
finally
{
if (con != null && con.State == ConnectionState.Open)
{
con.Close();
}
}
return result;
}
In above code there is a date time fdt. There may be duplicate msn but of different date time. I want to stop duplicate insertion of same date time and msn
Any help would be highly appreciated
im creating e grades project on c#, and i cant normally connect to database. Writing https://i.stack.imgur.com/itJuX.png
Maybe you can help me ? Not working in login.cs. Last job then i do it it was working.
private void button1_Click(object sender, EventArgs e)
{
try
{
using (SqlConnection conn = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\dienynas.mdf;Integrated Security=True;"))
{
conn.Open();
SqlCommand cmd = new SqlCommand("select * from users", conn);
SqlDataReader sdr = cmd.ExecuteReader();
int id = 0;
bool pass = false;
while (sdr.Read())
{
if (sdr[0].ToString() == textBox1.Text && sdr[0].ToString() == textBox2.Text)
{
pass = true;
id = (int)sdr[0];
break;
}
}
if (pass == false)
{
MessageBox.Show("Password for this user is incorrect");
id = (int)sdr[0];
pass = true;
}
else
{
Form1 frm = new Form1(id);
Hide();
frm.Show();
}
conn.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Your problem is in your if statement after the loop.
if (pass == false)
{
MessageBox.Show("Password for this user is incorrect");
id = (int)sdr[0];
pass = true;
}
In that if block you are accessing your SqlDataReader, which very possibly has exited the while loop after returning false upon reading indicating that there is no more data to be read. If there is no data, then you will get an error when attempting to read data that is not there.
I would think that one of the reasons you are exiting the while without ever having a match is that, unless both TextBox1 and TextBox2 contain a matching string you will never have a match. The following line is comparing those text box values to the exact same data value. Unless the text is identical between those text boxes then this statement will always be false.
if (sdr[0].ToString() == textBox1.Text && sdr[0].ToString() == textBox2.Text)
I am guessing that you intended something like this:
if (sdr[0].ToString() == textBox1.Text && sdr[1].ToString() == textBox2.Text)
Edit
With all of that being said, there is a lot of room for refactoring in this code. For one thing, generally performing database operations in a button handler can lead to unresponsive dialog windows and is something to be avoided. You are also using some other objects which are disposable and so you should be cleaning those up as well. I will rewrite the function a little to show you some of the cleanup, but I don't have time to go through splitting it into threads and it is outside the scope of your question.
private void button1_Click(object sender, EventArgs e)
{
SqlConnection conn = null;
SqlCommand cmd = null;
SqlDataReader sdr = null;
try
{
var textBox1 = textBox1.Text;
var textBox2 = textBox2.Text;
conn = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\dienynas.mdf;Integrated Security=True;");
conn.Open();
cmd = new SqlCommand("select * from users", conn);
sdr = cmd.ExecuteReader();
int id = -1;
while (sdr.Read())
{
var text0 = sdr[0].ToString();
var text1 = sdr[1].ToString();
// NOTE: You could add the string comparison type here as well
if (text0.Equals(textBox1) && text1.Equals(textBox2))
{
id = (int)sdr[0];
break;
}
}
if (id == -1)
{
MessageBox.Show("Password for this user is incorrect");
}
else
{
Form1 frm = new Form1(id);
Hide();
frm.Show();
}
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
sdr?.Dispose();
cmd?.Dispose();
conn?.Dispose();
}
}
guys..
I am training to create an existing bookstore app feature to add book stock and reduce book stock. when I create a stock added feature and save the transaction data of the stock addition, I get an error 'the connection is already open.' but I've closed all open connections. Please help me..
this is my code to show distributor id
public void loadDistributorID()
{
conn.Open();
cmd = conn.CreateCommand();
cmd.CommandText = "select id from distributor";
var reader = cmd.ExecuteReader();
while (reader.Read())
{
distributorPasok.Items.Add(reader.GetString("id"));
}
conn.Close();
}
this is my code to show book id
public void loadBukuID()
{
conn.Open();
cmd = conn.CreateCommand();
cmd.CommandText = "select id from buku";
var reader = cmd.ExecuteReader();
while (reader.Read())
{
bukuPasok.Items.Add(reader.GetString("id"));
}
conn.Close();
}
this is my code to add qty
public void increaseQty()
{
conn.Open();
cmd = conn.CreateCommand();
cmd.CommandText = "update buku set stok=stok + #jumlah where id=#id";
cmd.Parameters.AddWithValue("#jumlah", Convert.ToString(jumlahPasok.Value));
cmd.Parameters.AddWithValue("#id", bukuPasok.Text);
cmd.ExecuteNonQuery();
conn.Close();
}
this is my code to add the transaction data of the stock addition
try
{
if (distributorPasok.Text == "" || bukuPasok.Text == "" || jumlahPasok.Value == 0)
{
MessageBox.Show("Data harus terisi dengan valid!");
} else
{
conn.Open();
cmd = conn.CreateCommand();
cmd.CommandText = "insert into pasok (id_distributor, id_buku, jumlah, tanggal) values (#distributor, #buku, #jumlah, #tanggal)";
cmd.Parameters.AddWithValue("#distributor", distributorPasok.Text);
cmd.Parameters.AddWithValue("#buku", bukuPasok.Text);
cmd.Parameters.AddWithValue("#jumlah", Convert.ToString(jumlahPasok.Value));
cmd.Parameters.AddWithValue("#tanggal", Convert.ToDateTime(tanggalPasok.Text));
cmd.ExecuteNonQuery();
MessageBox.Show("Pasok telah ditambah!");
perbaruiPasok();
conn.Close();
}
} catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
and I've called all the classes into the add button.
The connection is already open indicates that the connection is still open when Open() method executed. If you remove all unrelated lines which controls opening & closing connection excluding flow control statements (if and try...catch block) for related methods, this is what you get:
// Method with try...catch
public void MethodName()
{
try
{
if (...)
{
// other stuff
}
else
{
conn.Open(); // --> opening DB connection
// other stuff
conn.Close(); // --> closing DB connection
}
}
catch (Exception ex)
{
// exception handling
}
}
// Other method
public void OtherMethodName()
{
// opening connection - will trigger exception if conn.Close in MethodName not executed!
conn.Open();
// other stuff
conn.Close();
}
When exception occurs between conn.Open() and conn.Close() command, it will go to catch clause but since conn.Close() is not declared there, the connection is still open when second conn.Open() executes.
What you need to fix is placing conn.Close() on finally block which always executed even an exception occurred inside try block:
try
{
if (...)
{
// other stuff
}
else
{
conn.Open();
// other stuff
}
}
catch (Exception ex)
{
// exception handling
}
finally
{
// always executed regardless of exception
if (conn.State == ConnectionState.Open)
conn.Close();
}
In much better way, it is recommended to use using statements which automatically calls Dispose() method (implicitly calls Close()) for IDisposable connection objects, see this example:
// declare connection string class-level instead of MySqlConnection
string connectionString = "server=localhost;database=buku;uid=fkrfdllh;pwd=*********"
try
{
if (empty_input)
{
MessageBox.Show("message text");
}
else
{
// wrap both MySqlConnection & MySqlCommand on using statements
using (var conn = new MySqlConnection(connectionString))
{
conn.Open();
using (var cmd = new MySqlCommand("[command_text]", conn))
{
cmd.Parameters.AddWithValue("[param_name]", value);
// other parameters here
cmd.ExecuteNonQuery();
MessageBox.Show("[success_message]");
// other methods
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Related issue:
Why do I get a "connection is already open" error during a MySQL update statement?
I'm created app to connect Oracle Database XE 11g with ODAC 12, and take an error called "invalid character".
This is my ConnectionString:
connectionString="Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=XE)));User Id=hr;Password=12345;"
and code here
private void BtnConnect_OnClick(object sender, RoutedEventArgs e)
{
var sql = #"SELECT FIRST_NAME FROM EMPLOYEES
WHERE EMPLOYEE_ID = 120;";
var command = new OracleCommand(sql, Connection.Connect);
try
{
command.Connection.Open();
var reader = command.ExecuteScalar();
if (reader != null)
{
LblMessage.Content = "Connect Succeeded ";
LblMessage.Foreground = Brushes.Green;
}
else
{
LblMessage.Content = "Connect Failed";
LblMessage.Foreground = Brushes.Red;
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
command.Connection.Close();
}
}
Somebody help me!
Standalone queries executed from your C# application shouldn't include the semicolon ; at the end. If you remove that, the ORA-00911 error should go away.