Building a dynamic SQL INSERT query with Where Clause C# - c#

I am using SQL Server 2012 & VS 2013. I have table schema like this
[dbo].[Accounts] ([AccntName], [AccntCrVal], [AccntDrVal])
I want to build a dynamic sql query depending on condition. User will select the AccoutnName and enter a Balance then choose balance type Credit or Debit. Now I want if user choose Credit values goes to credit column and vice versa. User will only select AccountName which already entered in the accounts table.
Currently I am doing this like this
using (SqlConnection conn = new SqlConnection(conStr))
{
insrtcmd = new SqlCommand();
insrtcmd.Connection = conn;
if (comBoxBalType.Text == "Cr")
{
insrtcmd.CommandText = #"INSERT INTO Accoutns(AccntCrVal) VALUES (#bal) Where(AccntName=#acntName)";
insrtcmd.Connection = conn;
insrtcmd.Parameters.AddWithValue("#acntName", acntName);
insrtcmd.Parameters.AddWithValue("#bal", bal);
conn.Open();
insrtcmd.ExecuteNonQuery();
}
else if (comBoxBalType.Text == "Dr")
{
insrtcmd.CommandText = #"INSERT INTO Accoutns(AccntDrVal) VALUES (#AccntDrVal) Where (AccntName=#prmSlctAcntName)";
insrtcmd.Connection = conn;
insrtcmd.Parameters.AddWithValue("#prmSlctAcntName", comBoxSlctAcnt.Text);
insrtcmd.Parameters.AddWithValue("#AccntDrVal", textBoxBal);
conn.Open();
insrtcmd.ExecuteNonQuery();
}
else
{
MessageBox.Show("Please Enter Values and Select the Balance Type [ Dr | Cr ] ", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
But I don't want to do like this. Thanks

As you already the data in the table, you need to Update the record. With your current setup, you can do something like this
using (SqlConnection conn = new SqlConnection(conStr))
{
var accountName = comBoxSlctAcnt.Text;
var balance = textBoxBal.Text;
var balanceType = comBoxBalType.Text;
if (balanceType == "Cr" || balanceType == "Dr")
{
insrtcmd = new SqlCommand();
insrtcmd.CommandText = string.Format(
#"UPDATE Accoutns SET {0} = #bal Where AccntName = #acntName",
balanceType == "Cr" ? "AccntCrVal" : "AccntDrVal");
insrtcmd.Connection = conn;
insrtcmd.Parameters.AddWithValue("#acntName", accountName);
insrtcmd.Parameters.AddWithValue("#bal", balance);
conn.Open();
insrtcmd.ExecuteNonQuery();
}
else
{
MessageBox.Show("Please Enter Values and Select the Balance Type [ Dr | Cr ] ", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
But, you should rather use a CheckBox or DropDown for selecting the transaction type, and also validate all the values before using them. Catch the exceptions, if any. Alternatively you can write a small stored proc and move the conditional logic from C# to SQL.

Related

Encountering a System.IndexOutOfRangeException: when trying to display data from two tables in a database

I am writing a form application. User inputs his name, email, address etc into text boxes as if he was ordering a package. If the user has already made an order once I want to make it possible for the user to enter his email into the text box and based on his email fill out all the other personal information needed for the package.
The trouble I am having is that his data is in two different tables. The data which is in customer table (his first and last name) I have successfully retrieved, but the data in the table address I don't know how to get.
Here is the code:
{
try
{
var connection = getConnection();
var command = new SqlCommand
{
Connection = connection,
CommandText = "SELECT * FROM Customer WHERE Email = #Email"
};
command.Parameters.Clear();
command.Parameters.AddWithValue("#Email", mailBox.Text);
connection.Open();
reader = command.ExecuteReader(CommandBehavior.SingleRow);
if (reader.Read())
{
fnameBox.Text = reader["fname"].ToString();
lnameBox.Text = reader["lname"].ToString();
command.CommandText = "SELECT * FROM address WHERE customerID= "+ reader["customerID"].ToString();
stateBox.Text = reader["state"].ToString(); //part where the error happens
cityBox.Text = reader["city"].ToString();
addressBox.Text = reader["address"].ToString();
zipBox.Text = reader["zip"].ToString();
int result = command.ExecuteNonQuery();
connection.Close();
if (result > 0)
{
MessageBox.Show("Success");
}
else
{
MessageBox.Show("Error");
}
}
else
{
MessageBox.Show("E-mail entered doesn't exist");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
} ```
Look into using something like EF in future, will clean such things up, but appreciate this is probably not feasible for what you're doing here.
You should get related data from multiple tables via SQL Joins (look into LEFT JOIN and INNER JOIN)
Your problem is caused by the result set not having a state field, which in turn is caused by your not actually executing your SELECT * FROM address query - you are setting the command text but doing nothing further. You need to create another DataReader for the second query and read those results.
Overall there's a lot of stuff to improve, but you're clearly at an early state in learning this so that's fine for now....
you didn't finish to read the first result and after this trying to get the second one
command.Parameters.Clear();
command.Parameters.AddWithValue("#Email", mailBox.Text);
var customerID=0;
var success=false;
connection.Open();
var reader1 = command.ExecuteReader();
if (reader1.Read())
{
sucess=true;
fnameBox.Text = reader1["fname"].ToString();
lnameBox.Text = reader1["lname"].ToString();
customerID= Convert.ToInt32( reader1["customerID"].ToString());
reader1.Close();
}
if( sucess)
{
command.CommandText = "SELECT * FROM address WHERE customerID = #CustomerID";
command.Parameters.Clear();
command.Parameters.AddWithValue("#CustomerID", customerID);
var reader2 = command.ExecuteReader();
sucess=false;
if (reader2.Read())
{
sucess=true;
stateBox.Text = reader2["state"].ToString();
cityBox.Text = reader2["city"].ToString();
addressBox.Text = reader2["address"].ToString();
zipBox.Text = reader2["zip"].ToString();
reader2.Close();
}
if (success)
{
MessageBox.Show("Success");
}
else
{
MessageBox.Show(" address select Error");
}
}
else
{
MessageBox.Show("E-mail entered doesn't exist");
}
connection.Close();

How to add foreign key in SQL Server in ASP.NET C#

I want to know how to add a foreign key into my website through the payment section which is I created a list Seminar for user to choose first including a schedule. After that, user can click register and redirect page into payment details form which is contains credit card or cash. after user make an payment and click confirm button then the database should be increase by one include the primary key of an id (auto generate).
My problem is why I am still getting an id which is -1 not even +1 (I checked, the database has not updated in SQL Server) because of an id is -1.
Here is my code regarding for the payment section
if (tbxName.Text != null && tbxCC.Text != null && ddlCCType.Text != null && tbxExpDate.Text != null)
{
ShoppingCart sc = (ShoppingCart)Session["cart"];
sc.Name = tbxName.Text;
if (rdbCash.Checked == true)
{
sc.OptionPay = rdbCash.Text;
}
else
{
sc.OptionPay = rdbCC.Text;
}
sc.CreditCard = tbxCC.Text;
sc.CreditCardType = ddlCCType.Text;
sc.SecurityCode = tbxCode.Text;
sc.CCExpiryDate = tbxExpDate.Text;
//sc.Registration.RegId = sc.Id;
int id = ShoppingCartDBMgr.purchaseSeminar(sc);
lblOutput.Text = "Confirm. order id is " + id;
//display output for payment successfully
//lblOutput.Text = "Payment Successfully!";
//make it null for amount, date and session of cart after transaction are being successful
lblAmount.Text = null;
lblDate.Text = null;
Session["cart"] = null;
My payment database manager code:
public static int purchaseSeminar(ShoppingCart sc)
{
int id = -1;
SqlConnection con = new SqlConnection(conStr);
try
{
SqlCommand command = new SqlCommand();
command.Connection = con;
command.CommandText = "insert into Payment (payment_id, payment_name, payment_ccNo, payment_ccType, payment_ccCode, payment_expDate, payment_price, payment_optionPay, payment_date, reg_id) values (#payment_id, #payment_name, #payment_ccNo, #payment_ccType, #payment_ccCode, #payment_expDate, #payment_price, #payment_optionPay, #payment_date, #reg_id)";
command.Parameters.AddWithValue("#payment_id", sc.Id);
command.Parameters.AddWithValue("#payment_ccNo", sc.CreditCard);
command.Parameters.AddWithValue("#payment_ccType", sc.CreditCardType);
command.Parameters.AddWithValue("#payment_ccCode", sc.SecurityCode);
command.Parameters.AddWithValue("#payment_expDate", sc.CCExpiryDate);
command.Parameters.AddWithValue("#payment_price", sc.TotalAmount);
command.Parameters.AddWithValue("#payment_optionPay", sc.OptionPay);
command.Parameters.AddWithValue("#reg_id", sc.Registration.RegId);
DateTime da = DateTime.Now;
command.Parameters.AddWithValue("#payment_date", da);
con.Open();
command.CommandText = "SET IDENTITY_INSERT Payment ON";
if (command.ExecuteNonQuery() > 0)
{
command.CommandText = "Select ##identity";
id = Convert.ToInt32(command.ExecuteScalar());
}
return id;
}
finally
{
con.Close();
}
}
This is not a good way of doing it however for your answer
you should add
This should be on your first line
command.CommandText = "SET IDENTITY_INSERT Payment On";
command.CommandText = "insert into Payment (payment_id, payment_name, payment_ccNo, payment_ccType, payment_ccCode, payment_expDate, payment_price, payment_optionPay, payment_date, reg_id) values (#payment_id, #payment_name, #payment_ccNo, #payment_ccType, #payment_ccCode, #payment_expDate, #payment_price, #payment_optionPay, #payment_date, #reg_id)";
command.Parameters.AddWithValue("#payment_id", sc.Id);
command.Parameters.AddWithValue("#payment_ccNo", sc.CreditCard);
command.Parameters.AddWithValue("#payment_ccType", sc.CreditCardType);
command.Parameters.AddWithValue("#payment_ccCode", sc.SecurityCode);
command.Parameters.AddWithValue("#payment_expDate", sc.CCExpiryDate);
command.Parameters.AddWithValue("#payment_price", sc.TotalAmount);
command.Parameters.AddWithValue("#payment_optionPay", sc.OptionPay);
command.Parameters.AddWithValue("#reg_id", sc.Registration.RegId);
And this should be your last line
command.CommandText = "SET IDENTITY_INSERT Payment OFF";
I don't see where sc.Id is being assigned a value unlike the others(eg: sc.Name). Then inserting that(sc.Id) into the database will insert a null value. So when you query it from the database, converting it to an int32 value, returns '-1'.
That's what I think might be causing the problem along with the structure of your code.
Since your id is auto-generated, exclude the 'payment_ID' from your insert command. Example:
command.CommandText = "insert into Payment (payment_name, payment_ccNo,
payment_ccType, payment_ccCode, payment_expDate, payment_price,
payment_optionPay, payment_date, reg_id)
values (#payment_name, #payment_ccNo, #payment_ccType, #payment_ccCode,
#payment_expDate, #payment_price, #payment_optionPay,
#payment_date, #reg_id)";
command.Parameters.AddWithValue("#payment_ccNo", sc.CreditCard);
command.Parameters.AddWithValue("#payment_ccType", sc.CreditCardType);
command.Parameters.AddWithValue("#payment_ccType", sc.CreditCardType);
command.Parameters.AddWithValue("#payment_ccCode", sc.SecurityCode);
command.Parameters.AddWithValue("#payment_expDate", sc.CCExpiryDate);
command.Parameters.AddWithValue("#payment_price", sc.TotalAmount);
command.Parameters.AddWithValue("#payment_optionPay", sc.OptionPay);
command.Parameters.AddWithValue("#reg_id", sc.Registration.RegId);
As an identity column, 'payment_ID' doesn't expect a value so exclude it from your insert statement. That way, you won't need to turn IDENTITY INSERT on. So you'll remove those statements too from your code.

Checking if int exists in array C#

I don’t know if this is the correct way to be doing this but I'm trying to get all Job Numbers from a database table and checking that what the user inputs is in the database. I’m doing this by sending all data to an array and checking if it exists in there. However I’m sure there will be an easier way. This is the code I have so far:
public class IDNo
{
public int Col1 { get; set; }
}
private void button3_Click(object sender, EventArgs e)
{
String check = "SELECT * FROM Job";
using (SqlConnection con = new SqlConnection(str))
{
using (SqlCommand cmd = new SqlCommand(check, con))
{
con.Open();
var listOfId = new List<IDNo>();
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var id = new IDNo();
id.Col1 = Convert.ToInt32(reader["JobNo"]);
listOfId.Add(id);
}
}
string JN = textBox10.Text;
int JoNo = Int32.Parse(JN);
if (JoNo == IDNo)
{
MessageBox.Show("No job number found, please try again!");
}
else
{
DO SOMETHING HERE WHEN CORRECT
}
}
}
}
I would just like some help on how to check if the number the user inputs exists in the array.
It is the database engine that should answer your question, not simply give you back all your job records and force your code through a, possible, very lengthy search of the matching data in your records...
int JoNo;
if(!Int32.TryParse(textBox10.Text, out JoNo))
{
MessageBox.Show("Not a valid number");
return;
}
String check = #"IF EXISTS( SELECT 1 FROM Job WHERE JobNo=#num)
SELECT 1 ELSE SELECT 0";
using (SqlConnection con = new SqlConnection(str))
using (SqlCommand cmd = new SqlCommand(check, con))
{
con.Open();
cmd.Parameters.Add("#num", SqlDbType.Int).Value = JoNo;
int result = (int)cmd.ExecuteScalar();
if(result == 0)
MessageBox.Show("No job number found, please try again!");
else
.....
}
First, you test if the user input is a valid number without throwning exceptions (Int32.TryParse) but just informing your user of the error, then you build an IF EXISTS query because you are just interested to know if the job number exists or not and you don't need to retrieve that value. Finally, the execution is done using ExecuteScalar because you are interested only in getting the single value 1 (for an existing JobNo or 0 for a not exisisting JobNo.
You can use the jobNo which is sent by the user as an input parameter for your search query in database. So you can simply do it using the query:
SqlCommand check = new SqlCommand("SELECT * FROM Job where JobNo = #JobNo" , conn);
check.Parameters.AddWithValue("#JobNo", id.Text);
int exists = (int)check.ExecuteScalar();
if(exists > 0)
{
//job no exist
}
else
{
//job no doesn't exist.
}

C# winform login using Ms Access 2013

I am creating a C# windows login form using MS Access 2013.
Login form using User ID(Autonumber) and Password(Short text).
My problem here is, it always crash(or Syntax error I guess) every time I click the LOGIN button and I can't trace the problem since I'm still inexperience in programming.
Table User
Fields: user_Id(Auto Number), password(short text), name(short text), type(number)
private void btn_Login_Click(object sender, EventArgs e)
{
try
{
if (string.IsNullOrEmpty(txt_UserId.Text))
{
lbl_warningUser.Visible = true;
lbl_warningUser.Text = "User ID is Empty";
}
if (string.IsNullOrEmpty(txt_Password.Text))
{
lbl_warningPass.Visible = true;
lbl_warningPass.Text = "Password is Empty";
}
if (txt_UserId.Text !="" & txt_Password.Text != "")
{
string constring = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Database/Health.accdb;";
string query = ("SELECT COUNT(*) FROM User WHERE user_Id = #ID AND password = #Pass");
using (OleDbConnection con = new OleDbConnection(constring))
using (OleDbCommand cmd = new OleDbCommand(query, con))
{
con.Open();
cmd.Parameters.AddWithValue("#ID", txt_UserId.Text);
cmd.Parameters.AddWithValue("#Pass", txt_Password.Text);
int result = (int)cmd.ExecuteScalar();
if (result > 0)
{
MessageBox.Show("Successfully Login");
con.Close();
this.Hide();
MainUI m = new MainUI();
m.Show();
}
else
{
MessageBox.Show("Incorrect User ID or Password");
}
con.Close();
}
}
}
catch (Exception ex)
{
MessageBox.Show(" "+ex);
}
}
User is a reserved word in MS Access I think, so you need to wrap it in square bracket delimiters. Also, you likely need to specify an alias for the COUNT function result:
"SELECT COUNT(*) AS qtyUsers FROM [User] WHERE user_Id = #ID AND password = #Pass"
txt_UserId.Text has a default return value of string, did you convert the value to an integer then try actually autonumber is integer.
First convert your value and try
Convert.ToInt32(txt_UserId.Text)

select *from table1 where id='"+comboBox1.Text+"'and name='"+comboBox2.Text+"'

I want to execute this command
select * from table1 where id='"+comboBox1.Text+"'and name='"+comboBox2.Text+"'
but I don't want them to be considered if they were empty, for example if combobox1.Text is empty, I want the command to be like
select * from table1 where name='"+comboBox2.Text+"'
You can have a check with the text boxes like
if (comboBox1.Text.Trim().Length == 0) {
// your query
}
else{
// other query
}
But you should be using parameterised queries. Building up your queries like that leaves you open to SQL injection.
So your SQL String should be
select * from table1 where id=#id and name=#name
And you add the parameters to the command object before executing the query.
You can build up your query as you go, and still protect yourself from SQL injection:
(I'm writing this from memory, it should compile...)
using (var conn = new SqlConnection("..."))
{
var sb = new StringBuilder("SELECT * FROM table1 WHERE");
using (var cmd = new SqlCommand { Connection = conn })
{
if (!String.IsNullOrEmpty(comboBox1.Text))
{
sb.Append(" id = #ID");
cmd.Parameters.AddWithValue("#ID", int.Parse(comboBox1.Text));
}
if (!String.IsNullOrEmpty(comboBox2.Text))
{
sb.Append(" name = #NAME");
cmd.Parameters.AddWithValue("#NAME", comboBox2.Text);
}
var query = sb.ToString();
cmd.CommandText = query.EndsWith("WHERE") ? query.Remove(query.Length - 5) : query;
conn.Open();
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// do whatever you need to do with your data
}
}
}
}
Something to keep in mind...
This could get out of hand if you have a dozen if blocks instead of just two, and then start nesting more if blocks inside of those. Maintenance will become a nightmare.
It may just be easier, if you only have a few conditions, to just create a few separate queries and determine which one is called instead of building a query dynamically like this.
i found the solution i want
MySqlDataAdapter cmd = new MySqlDataAdapter("select * from table1 where (ID=#id or #id2) and (name=#name or #name2) ", co);
if (comboBox1.Text == "")
{
cmd.SelectCommand.Parameters.AddWithValue("#id", "1");
cmd.SelectCommand.Parameters.AddWithValue("#id2", "1");
}
else
{
cmd.SelectCommand.Parameters.AddWithValue("#id", comboBox1.Text);
cmd.SelectCommand.Parameters.AddWithValue("#id2", "0");
}
if (comboBox2.Text == "")
{
cmd.SelectCommand.Parameters.AddWithValue("#name", "1");
cmd.SelectCommand.Parameters.AddWithValue("#name2", "1");
}
else
{
cmd.SelectCommand.Parameters.AddWithValue("#name", comboBox1.Text);
cmd.SelectCommand.Parameters.AddWithValue("#name2", "0");
}
//thanks everyone for the help , i used all what u gave me to create this solution

Categories

Resources