C# SQL AND condition not working on string data - c#

I was hoping someone could help me out with this stupid problem I'm having with the following SQL statement:
public void ApplyInference(string AnswerSelected)
{
int InferenceID;
int QuestionID;
string AnswerInference;
int PainValue;
int AnxietyValue;
int DepressionValue;
int FearValue;
int TransportValue;
int EmotionalValue;
int FinancialValue;
int PhysicalValue;
int SpiritValue;
int SocialValue;
SqlConnection NewConnection = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\QuestionsDatabase.mdf;Integrated Security=True;User Instance=True"); //"Initial Catalog=Northwind;Integrated Security=SSPI");
SqlDataReader ReadIn = null;
try
{
NewConnection.Open();
SqlCommand GetInference = new SqlCommand("SELECT * FROM InferenceDB WHERE QuestionID =" + this.QuestionID + "AND AnswerInference =" + AnswerSelected, NewConnection);
ReadIn = GetInference.ExecuteReader();
while (ReadIn.Read())
{
InferenceID = Convert.ToInt32(ReadIn[0]);
QuestionID = Convert.ToInt32(ReadIn[1]);
AnswerInference = Convert.ToString(ReadIn[2]);
PainValue = Convert.ToInt32(ReadIn[3]);
AnxietyValue = Convert.ToInt32(ReadIn[4]);
DepressionValue = Convert.ToInt32(ReadIn[5]);
FearValue = Convert.ToInt32(ReadIn[6]);
TransportValue = Convert.ToInt32(ReadIn[7]);
EmotionalValue = Convert.ToInt32(ReadIn[8]);
FinancialValue = Convert.ToInt32(ReadIn[9]);
PhysicalValue = Convert.ToInt32(ReadIn[10]);
SpiritValue = Convert.ToInt32(ReadIn[11]);
SocialValue = Convert.ToInt32(ReadIn[12]);
MessageBox.Show("InferenceID: " + InferenceID + "\nAnswer Value: " + AnswerInference + "\nPain value: " + PainValue + "\nSocial value: " + SocialValue);
//LoadQuestionForm(this.FormStyle);
}
}
finally
{
if (ReadIn != null)
{
ReadIn.Close();
}
if (NewConnection != null)
{
NewConnection.Close();
}
}
}`
Now the code works tor every other column in the table except for the one I need which is the AnswerInference one. I am feeding the AnswerInference value in from another method which looks like this:
private void Answer1Button_Click(object sender, EventArgs e)
{
parent.ApplyInference("Ans1");
CloseForm();
}
Unfortunately I can't get the code to work using string data found in the table I'm using. I know this should be an easy fix, but I can for the life of me work out what's going on. Can someone suggest what I'm doing wrong?

You need a space between the question-id and the and, but more importantly: you should use parameters. Look into "SQL injection", query-plan re-use, etc. The most appropriate way to do this is with a command like:
using(var GetInference = new SqlCommand(#"
SELECT *
FROM InferenceDB
WHERE QuestionID = #questionID AND AnswerInference = #answerInference"
, NewConnection);
{
GetInference.Parameters.AddWithValue("questionID", QuestionID);
GetInference.Parameters.AddWithValue("answerInference", AnswerSelected);
....
}
Also - that complex-looking try/finally can be simplified with using here.

You need a space before the AND
"SELECT *
FROM InferenceDB
WHERE QuestionID = " + this.QuestionID + " AND AnswerInference = " + AnswerSelected

Related

Mysql update query works without using parameters but doesn't when using them

Good day,
In c#, I am trying to run a MySQL update query to update one record, based on its id. Everything goes well as long as I'm not using parameters.
I'm experiencing the issue once I am adding one or several parameters. I have made the test with only one parameter and same problem here.
What am I missing here ?
Thank you very much for your help.
public static void editCustomerTest(ClsCustomerTest pTest)
{
MySqlConnection l_Connection = null;
string l_SpName = string.Empty;
MySqlCommand l_MyCommand = null;
try
{
l_Connection = ClsIconEnv.getDataAccess().MySqlConnection;
ClsDataAccess.OpenConnection(l_Connection);
l_SpName = "update tbTestCustomers " +
"set sName = '#sLastName', " +
"sFirstName = '#sFirstName', " +
"sAddress = '#sAddress' " +
"Where id = #id);";
l_MyCommand = new MySqlCommand(l_SpName, l_Connection);
l_MyCommand.Parameters.Add("#sLastName", pTest.Last_Name);
l_MyCommand.Parameters.Add("#sFirstName", pTest.First_name);
l_MyCommand.Parameters.Add("#sAddress", pTest.Address);
l_MyCommand.Parameters.Add("#id", pTest.id);
l_MyCommand.ExecuteNonQuery(); // <----- This is the line at which the execution stops
ClsDataAccess.CloseConnection(l_Connection);
}
catch (Exception exc)
{
ClsIconErrorManager.manageException(exc);
}
finally
{
}
}
You do not need to wrap your params into the string and you have to use AddWithValue instead of Add if you don't want to explicitly specify the type, like this
l_SpName = "update tbTestCustomers " +
"set sName = #sLastName, " +
"sFirstName = #sFirstName, " +
"sAddress = #sAddress" +
"Where id = #id);";
l_MyCommand.Parameters.AddWithValue("#sLastName", pTest.Last_Name);
l_MyCommand.Parameters.AddWithValue("#sFirstName", pTest.First_name);
l_MyCommand.Parameters.AddWithValue("#sAddress", pTest.Address);
l_MyCommand.Parameters.AddWithValue("#id", pTest.id);
Like this:
l_SpName = #"update tbTestCustomers
set sName = #sLastName,
sFirstName = #sFirstName,
sAddress = #sAddress
Where id = #id";
l_MyCommand = new MySqlCommand(l_SpName, l_Connection);
l_MyCommand.Parameters.AddWithValue("#sLastName", pTest.Last_Name);
l_MyCommand.Parameters.AddWithValue("#sFirstName", pTest.First_name);
l_MyCommand.Parameters.AddWithValue("#sAddress", pTest.Address);
l_MyCommand.Parameters.AddWithValue("#id", pTest.id);
l_MyCommand.ExecuteNonQuery();

How to obtain data from UserControl to Form? C# WinForms and SQLite

I know that this question has been asked, but unfortunately most of the answers did not solve the problem. So hopefully someone can help me :)
So here is my problem.
I want to get this data from StudentLedgerControl (I encircled it with red). Then transfer this data to a form called StudentLedgerWindow.
Although before all of this, a button must be clicked to show the StudentLedgerWindow, which once showed, the transferred data will appear.
StudentLedgerControl.cs
public void LoadStudentLedger(SQLiteConnection conn)
{
SQLiteCommand sqlite_cmd;
sqlite_cmd = new SQLiteCommand("SELECT * FROM Student", conn);
SQLiteDataReader read = sqlite_cmd.ExecuteReader();
StudentFlowPanel.SuspendLayout();
StudentFlowPanel.Controls.Clear();
while (read.Read())
{
sc = new StudentControl();
sc.StudentIDLabel.Text = "Student ID: " + read.GetInt32(0).ToString(); // id
sc.StudentNameLabel.Text = read.GetString(1) + " " + read.GetString(2) + " " + read.GetString(3); // fullname
sc.StudentSectionLabel.Text = "Section: " + read.GetString(4); // section
sc.StudentLevelLabel.Text = "Level: " + read.GetInt32(5).ToString(); // level
StudentFlowPanel.Controls.Add(sc);
}
StudentFlowPanel.ResumeLayout();
}
StudentLedgerWindow (expected outcome)
Show Window Button Event and User Interface
private void ViewLedgerButton_Click(object sender, EventArgs e)
{
// Once clicked, the data should show on StudentLedgerWindow
}
Thank You in Advance :)
P.S. I'm new here, so if there are any problems with my post pls tell me so that I can change it.
I think I solved it... idk probably...
All I did is create getters and setters (kek, I should have tried this first)
Then calling the getters and setters. (if that makes sense, hopefully it does)
Old Code
public void LoadStudentLedger(SQLiteConnection conn)
{
SQLiteCommand sqlite_cmd;
sqlite_cmd = new SQLiteCommand("SELECT * FROM Student", conn);
SQLiteDataReader read = sqlite_cmd.ExecuteReader();
StudentFlowPanel.SuspendLayout();
StudentFlowPanel.Controls.Clear();
while (read.Read())
{
sc = new StudentControl();
sc.StudentIDLabel.Text = "Student ID: " + read.GetInt32(0).ToString(); // id
sc.StudentNameLabel.Text = read.GetString(1) + " " + read.GetString(2) + " " + read.GetString(3); // fullname
sc.StudentSectionLabel.Text = "Section: " + read.GetString(4); // section
sc.StudentLevelLabel.Text = "Level: " + read.GetInt32(5).ToString(); // level
StudentFlowPanel.Controls.Add(sc);
}
StudentFlowPanel.ResumeLayout();
}
New Code
public void LoadStudentLedger(SQLiteConnection conn)
{
SQLiteCommand sqlite_cmd;
sqlite_cmd = new SQLiteCommand("SELECT * FROM Student", conn);
SQLiteDataReader read = sqlite_cmd.ExecuteReader();
StudentFlowPanel.SuspendLayout();
StudentFlowPanel.Controls.Clear();
while (read.Read())
{
sc = new StudentControl();
sc.StudentId = "Student ID: " + read.GetInt32(0).ToString(); // id
sc.StudentName = read.GetString(1) + " " + read.GetString(2) + " " + read.GetString(3); // fullname
sc.StudentSection = "Section: " + read.GetString(4); // section
sc.StudentLevel = "Level: " + read.GetInt32(5).ToString(); // level
sc.StudentIDLabel.Text = "Student ID: " + read.GetInt32(0).ToString(); // id
sc.StudentNameLabel.Text = read.GetString(1) + " " + read.GetString(2) + " " + read.GetString(3); // fullname
sc.StudentSectionLabel.Text = "Section: " + read.GetString(4); // section
sc.StudentLevelLabel.Text = "Level: " + read.GetInt32(5).ToString(); // level
StudentFlowPanel.Controls.Add(sc);
}
StudentFlowPanel.ResumeLayout();
}
Getters and Setters
public string _StudentName;
public string _StudentSection;
public string _StudentLevel;
public string _StudentId;
public string StudentName
{
get { return _StudentName; }
set { _StudentName = value; }
}
public string StudentSection
{
get { return _StudentSection; }
set { _StudentSection = value; }
}
public string StudentLevel
{
get { return _StudentLevel; }
set { _StudentLevel = value; }
}
public string StudentId
{
get { return _StudentId; }
set { _StudentId = value; }
}
Thank You :)
And also if there are any code improvements I can do please let me know :)

Visual Studio Database Not Updating

I am working on a school project and for some reason my mysql database doesn't update despite no of row changed is more than 0 and triggering the Update sucessful alert. It also manage to only update my image data from my fileupload.
**admin_products_details_edit.aspx.cs**
protected void btn_ProdEdit_Click(object sender, EventArgs e)
{
int result = 0;
string image = "";
if (FileUpload_ProdImg.HasFile == true)
{
image = "images\\" + FileUpload_ProdImg.FileName;
img_result.ImageUrl = FileUpload_ProdImg.FileName;
}
else
{
image = img_result.ImageUrl;
}
Product Prod = new Product();
string datProdID = lbl_ProdID.Text;
string datProdName = tb_ProdName.Text;
string datProdDesc = tb_ProdDesc.Text;
string datProdImg = img_result.ImageUrl;
decimal datProdPrice = decimal.Parse(tb_ProdPrice.Text);
int datProdCal = int.Parse(tb_ProdCal.Text);
int datStockLvl = int.Parse(tb_StockLvl.Text);
result = Prod.ProductUpdate(datProdID, datProdName, datProdDesc, datProdImg, datProdPrice, datProdCal, datStockLvl);
if (result > 0)
{
string saveimg = Server.MapPath(" ") + "\\" + image;
FileUpload_ProdImg.SaveAs(saveimg);
Response.Write("<script>alert('Update successful');</script>");
Response.Redirect("admin_products_details.aspx?ProdID=" + datProdID);
}
else
{
Response.Write("<script>alert('Update fail');</script>");
}
}<-The code for the button edit event trigger
**Product.cs**
...public int ProductUpdate(string upID, string upName, string upDesc, string upImg, decimal upPrice, int upCal, int upstkLvl)
{
string queryStr = "UPDATE Products SET" + " ProdName = #productName, " + " ProdDesc = #productDesc, " + " ProdImg = #productImage, " + " ProdPrice = #productPrice, " + " ProdCalorie = #productCal, " + " StockLevel = #productStkLvl " + " WHERE ProdID = #productID";
SqlConnection conn = new SqlConnection(_connStr);
SqlCommand cmd = new SqlCommand(queryStr, conn);
cmd.Parameters.AddWithValue("#productID", upID);
cmd.Parameters.AddWithValue("#productName", upName);
cmd.Parameters.AddWithValue("#productDesc", upDesc);
cmd.Parameters.AddWithValue("#productImage", upImg);
cmd.Parameters.AddWithValue("#productPrice", upPrice);
cmd.Parameters.AddWithValue("#productCal", upCal);
cmd.Parameters.AddWithValue("#productStkLvl", upstkLvl);
conn.Open();
int nofRow = 0;
nofRow = cmd.ExecuteNonQuery();
conn.Close();
return nofRow;
}<-The code for updating the mysql database,located in a different cs file,titled Product.cs
My mysql database table is called Products
Thank you very much for your help in advance.

C# Fatal error encoutered during data read

I'm selecting about 20,000 records from the database and then I update them one by one.
I looked for this error and I saw that setting the CommandTimeout will help, but not in my case.
public void Initialize()
{
MySqlConnectionStringBuilder SQLConnect = new MySqlConnectionStringBuilder();
SQLConnect.Server = SQLServer;
SQLConnect.UserID = SQLUser;
SQLConnect.Password = SQLPassword;
SQLConnect.Database = SQLDatabase;
SQLConnect.Port = SQLPort;
SQLConnection = new MySqlConnection(SQLConnect.ToString());
}
public MySqlDataReader SQL_Query(string query)
{
MySqlCommand sql_command;
sql_command = SQLConnection.CreateCommand();
sql_command.CommandTimeout = int.MaxValue;
sql_command.CommandText = query;
MySqlDataReader query_result = sql_command.ExecuteReader();
return query_result;
}
public void SQL_NonQuery(string query)
{
MySqlCommand sql_command;
sql_command = SQLConnection.CreateCommand();
sql_command.CommandTimeout = int.MaxValue;
sql_command.CommandText = query;
sql_command.ExecuteNonQuery();
}
And here is my method which makes the select query:
public void CleanRecords()
{
SQLActions.Initialize();
SQLActions.SQL_Open();
MySqlDataReader cashData = SQLActions.SQL_Query("SELECT `cash`.`id`, SUM(`cash`.`income_money`) AS `income_money`, `cash_data`.`total` FROM `cash_data` JOIN `cash` ON `cash`.`cash_data_id` = `cash_data`.`id` WHERE `user`='0' AND `cash_data`.`paymentterm_id`='0' OR `cash_data`.`paymentterm_id`='1' GROUP BY `cash_data_id`");
while(cashData.Read()){
if(cashData["income_money"].ToString() == cashData["total"].ToString()){
UpdateRecords(cashData["id"].ToString());
}
}
SQLActions.SQL_Close();
}
And here is the method which makes the update:
public void UpdateRecords(string rowID)
{
SQLActions.Initialize();
SQLActions.SQL_Open();
SQLActions.SQL_NonQuery("UPDATE `cash_data` SET `end_date`='" + GetMeDate() + "', `user`='1' WHERE `id`='" + rowID + "'");
SQLActions.SQL_Close();
}
Changing the database structure is not an option for me.
I thought that setting the timeout to the maxvalue of int will solve my problem, but is looks like this wont work in my case.
Any ideas? :)
EDIT:
The error which I get is "Fatal error encoutered during data read".
UPDATE:
public void CleanRecords()
{
StringBuilder dataForUpdate = new StringBuilder();
string delimiter = "";
SQLActions.Initialize();
SQLActions.SQL_Open();
MySqlDataReader cashData = SQLActions.SQL_Query("SELECT `cash`.`id`, SUM(`cash`.`income_money`) AS `income_money`, `cash_data`.`total` FROM `cash_data` JOIN `cash` ON `cash`.`cash_data_id` = `cash_data`.`id` WHERE `user`='0' AND `cash_data`.`paymentterm_id`='0' OR `cash_data`.`paymentterm_id`='1' GROUP BY `cash_data_id`");
while (cashData.Read())
{
if (cashData["income_money"].ToString() == cashData["total"].ToString())
{
dataForUpdate.Append(delimiter);
dataForUpdate.Append("'" + cashData["id"].ToString() + "'");
delimiter = ",";
}
}
SQLActions.SQL_Close();
UpdateRecords(dataForUpdate.ToString());
}
public void UpdateRecords(string rowID)
{
SQLActions.Initialize();
SQLActions.SQL_Open();
SQLActions.SQL_NonQuery("UPDATE `cash_data` SET `end_date`='" + GetMeDate() + "', `user`='1' WHERE `id` IN (" + rowID + ")");
SQLActions.SQL_Close();
}
You may be able to use
UPDATE cash_data .... WHERE id IN (SELECT ....)
and do everything in one go. Otherwise, you could do it in two steps: first the select collects all the ids, close the connection and then do the update in obne go with all the ids.
The code for the second option might look something like this:
public void CleanRecords()
{
StringBuilder builder = new StringBuilder();
string delimiter = "";
SQLActions.Initialize();
SQLActions.SQL_Open();
MySqlDataReader cashData = SQLActions.SQL_Query("SELECT `cash`.`id`, SUM(`cash`.`income_money`) AS `income_money`, `cash_data`.`total` FROM `cash_data` JOIN `cash` ON `cash`.`cash_data_id` = `cash_data`.`id` WHERE `user`='0' AND `cash_data`.`paymentterm_id`='0' OR `cash_data`.`paymentterm_id`='1' GROUP BY `cash_data_id`");
while(cashData.Read()){
if(cashData["income_money"].ToString() == cashData["total"].ToString()){
builder.Append(delimiter);
builder.Append("'" + cashData["id"].ToString() + "'");
delimiter = ",";
}
}
SQLActions.SQL_Close();
UpdateRecords(builder.ToString());
}
public void UpdateRecords(string rowIDs)
{
SQLActions.Initialize();
SQLActions.SQL_Open();
SQLActions.SQL_NonQuery("UPDATE `cash_data` SET `end_date`='" + GetMeDate() + "', `user`='1' WHERE `id` IN (" + rowIDs + ")";
SQLActions.SQL_Close();
}
There are multiple problem:
First: You have reading information around 20K using data reader and then doing update one by one in reader itself. Reader holds the connection open until you are finished. So this is not the good way to do it. Solution: We can read the information using Data Adapter.
Second: Rather than doing one by one update, we can update in bulk in one go. There are multiple option for bulk operation. In SQL u can do either by sending information in XML format or u can use Table Valued Parameter (TVP) (http://www.codeproject.com/Articles/22205/ADO-NET-and-OPENXML-to-Perform-Bulk-Database-Opera) OR (http://dev.mysql.com/doc/refman/5.5/en/load-xml.html)

Passing same value of method to multiple forms

In my window application I have orderNumber that need to be passed to another form. This order number is generated by the code which I will put below. I am trying to pass only 1 identical order number to two locations but unfortunately, two different order number passed to both location. How can I make that only one order number is passed to both location.
Code that generates the order number:
public string orderNumber()
{
string ord = "ORD" + get_next_id() + DateTime.Now.Year;
return ord;
}
public int get_next_id()
{
OleDbConnection objConnection = null;
OleDbCommand objCmd = null;
String sql;
int res;
// Create and open the connection object
objConnection = new OleDbConnection(connString);
objConnection.Open();
sql = "SELECT IIF(MAX(Customer.NumGenerate) IS NULL,100,MAX(Customer.NumGenerate)) as v_max FROM Customer;";
objCmd = new OleDbCommand(sql, objConnection);
res = (int)objCmd.ExecuteScalar();
++res;
objConnection.Close();
return res;
}
In the first form the following insert method uses the order number:
private void SaveAllListItems()
{
string listItems = string.Empty;
foreach (var listBoxItem in listBox1.Items)
{
listItems += listBoxItem.ToString();
if (listBox1.Items.IndexOf(listBoxItem) < listBox1.Items.Count - 1)
{
listItems += ", ";
}
}
InsertUser(maskedTextBox1.Text, comboBox1.Text, maskedTextBox2.Text, maskedTextBox3.Text, maskedTextBox4.Text, maskedTextBox5.Text,
maskedTextBox6.Text, maskedTextBox7.Text, maskedTextBox8.Text, maskedTextBox9.Text, listItems, DateTime.Now, maskedTextBox10.Text, orderNumber(), get_next_id());
;
}
In second form I want to use the same order number which is being used to insert user. right now I have the following code which is not working as form1 has different order number and form 2 has different.
private void FindOrder()
{
Form1 m = new Form1();
string number = m.orderNumber();
// string number = "ORD1012013";
string InvSql = "SELECT (Customer.[Title] + SPACE(2) + Customer.[Customer's Name]) as CustomerName, Customer.[Customer's Ebayname], Customer.[Email Address], Customer.[Phone Number], (Customer.[Address 1] + SPACE(2) +Customer.[Address 2] + SPACE(2) + Customer.[City] + SPACE(2) + Customer.[Post Code]+ SPACE(2) + Customer.[Country]) as Address, Customer.[Item Purchased], Customer.[Purchased Date], Customer.[Total Price], Customer.[OrderNumber] FROM Customer WHERE Customer.[OrderNumber]= '" + number + "'";
OleDbConnection cnn = new OleDbConnection(connString);
OleDbCommand cmdOrder = new OleDbCommand(InvSql, cnn);
cnn.Open();
OleDbDataReader rdrOrder = cmdOrder.ExecuteReader();
rdrOrder.Read();
custName.Text = rdrOrder["CustomerName"].ToString();
ebayName.Text = rdrOrder["Customer's Ebayname"].ToString();
email.Text = rdrOrder["Email Address"].ToString();
phone.Text = rdrOrder["Phone Number"].ToString();
address.Text = rdrOrder["Address"].ToString();
item.Text = rdrOrder["Item Purchased"].ToString();
date.Text = Convert.ToString(Convert.ToDateTime(rdrOrder["Purchased Date"]));
price.Text = rdrOrder["Total Price"].ToString();
order.Text = rdrOrder["OrderNumber"].ToString();
rdrOrder.Close();
cnn.Close();
}
How can I pass same order number to both location?
Data can be passed between forms in different ways.
Here's a good tutorial on how to do that.The Constructor and Property approach is easier to implement.
You dont seem to be saving the orderid on the form1 class
Declare a variable for the OrderID on Form1 class
string OrderId;
Modify your exisiting Method
public string orderNumber()
{
OrderId = "ORD" + OrderId + DateTime.Now.Year;
}
And then follow the Constructor Approach to pass over the value to PrintForm
Again declare a variable for orderID inside the PrintForm class
string OrderId;
Change your PrintForm Constructor to this
public PrintForm(string value)
{
InitializeComponent();
OrderId=value;
}
on Form1 Button click event
private void button1_Click(object sender, System.EventArgs e)
{
PrintForm frm=new PrintForm(OrderId);
PrintForm.Show();
}
Create a container class with a static property in the same namespace:
class clsDummy
{
internal static string ptyValue { get; set; }
}
you can assign this property where you are getting order id:
public string orderNumber()
{
string ord = "ORD" + get_next_id() + DateTime.Now.Year;
clsDummy.ptyValue =ord ;
return ord;
}
after that where ever you want to access just check value inside : clsDummy.ptyValue

Categories