Update query and Connection property has not been initialized - c#

i passed a value from form1 to form2 and used that value as a where condition however i cant seem to fix it. I'm updating a table btw. any help would be greatly appreciated.
SqlConnection cn = new SqlConnection("Data Source=DESKTOP-MQKIBSK\\SQLEXPRESS;Initial Catalog=inventory2;Integrated Security=True");
SqlCommand cmd = new SqlCommand();
SqlDataAdapter adptr = new SqlDataAdapter();
DataSet dt = new DataSet();
private void button1_Click(object sender, EventArgs e)
{
if (this.Text == "EDIT")
{
cmd.CommandText = string.Format("Update Items Set (Barcode='" + txtcode.Text + "' ,Productname= '" + txtitemname.Text + "',Prices= '" + txtPrices.Text + "' ,Quantity= '" + txtquantity.Text + "' ,Brand= '" + txtbrand.Text + "',Expiry= '" + txtexpiry.Text + "',Description='" + txtdescription.Text + "' ,Critical= '" + txtcritical.Text + "' where Barcode = '" + txtTry.Text + "')", cn);
cmd.ExecuteNonQuery();
MessageBox.Show("Records Updated!");
txtcode.Text = "";
txtitemname.Text = "";
txtPrices.Text = "";
txtquantity.Text = "";
txtbrand.Text = "";
txtexpiry.Text = "";
txtdescription.Text = "";
txtcritical.Text = "";
}
else
{
MessageBox.Show("Invalid");
}

I think the error message is clear enough, you have to assign the connection to the command which is going to be executed. But here you may face another big issue, ie., the SqlInjection because of this concatenated query text query, You have to use parameterization instead to avoid the injection, in short your code would be looks like the following:
string connectioStr = "Data Source=DESKTOP-MQKIBSK\\SQLEXPRESS;Initial Catalog=inventory2;Integrated Security=True";
string querySQL = "Update Items Set Barcode=#Barcode,Productname=#Productname,Prices=#Prices,Quantity=#Quantity where Barcode = #condition";
// add more columns as you needed in the set
using (SqlConnection conSQL = new SqlConnection(connectioStr))
{
using (SqlCommand cmdSQL = new SqlCommand())
{
cmdSQL.Connection = conSQL;
cmdSQL.CommandText = querySQL;
cmdSQL.Parameters.Add("#Barcode", SqlDbType.VarChar).Value = txtcode.Text;
cmdSQL.Parameters.Add("#Productname", SqlDbType.VarChar).Value = txtitemname.Text;
cmdSQL.Parameters.Add("#Prices", SqlDbType.VarChar).Value = txtPrices.Text;
cmdSQL.Parameters.Add("#Quantity", SqlDbType.VarChar).Value = txtquantity.Text;
cmdSQL.Parameters.Add("#condition", SqlDbType.VarChar).Value = txtcode.Text;
// Add all parameters specified in the query
// use appropriate datatypes as per the type of columns
}
}
You can specify the connection and query of the command at the time of initializing the command; in this case the command initialization would be like this:
SqlCommand cmdSQL = new SqlCommand(querySQL,conSQL);

Related

Connection is not closed properly ASP.NET C#

I have this button click event. Been trying to replace the con.Close() in different lines of code, tried for hours but couldn't fix. Maybe a second pair of eyes can help?
Error: System.InvalidOperationException: 'The connection was not closed. The connection's current state is open.'
protected void Button1_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection();
con.ConnectionString = ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString;
con.Open();
string query = "SELECT CATEGORY FROM CATEGORY WHERE C_UserName = '" + Session["id"] + "' AND CATEGORY = '" + DropDownList1.SelectedItem.Value + "' ";
SqlCommand cmd = new SqlCommand(query, con);
SqlDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
cmd.Parameters.AddWithValue("#CATEGORY", DropDownList1.SelectedItem.Value);
lblResult.Text = "You have selected this category. Please select a new category";
con.Close();
}
else
{
SqlCommand cmd1 = new SqlCommand("UPDATE SET CATEGORY CCID#CCID (CATEGORY, C_USERNAME, CCID) VALUES (#CATEGORY, #C_USERNAME, #CCID)", con);
cmd1.Parameters.AddWithValue("CATEGORY", DropDownList1.SelectedItem.Value);
cmd1.Parameters.AddWithValue("C_USERNAME", Session["id"]);
cmd1.Parameters.AddWithValue("CCID", Label1.Text);
con.Open();
int i = cmd1.ExecuteNonQuery();
con.Close();
if (i != 0)
{
Label2.Text = " Your data is been saved in the database";
Label2.ForeColor = System.Drawing.Color.ForestGreen;
}
else
{
Label2.Text = "Something went wrong with selection";
Label2.ForeColor = System.Drawing.Color.Red;
}
}
}
Try this (open connection only once and close only once):
protected void Button1_Click(object sender, EventArgs e) {
using(SqlConnection con = new SqlConnection()) {
con.ConnectionString = ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString;
string query = "SELECT CATEGORY FROM CATEGORY WHERE C_UserName = '" + Session["id"] + "' AND CATEGORY = '" + DropDownList1.SelectedItem.Value + "' ";
SqlCommand cmd = new SqlCommand(query, con);
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
bool hasRows = reader.HasRows;
reader.Close();
if (hasRows) {
// This line makes no sense after the execution of the query.
//cmd.Parameters.AddWithValue("#CATEGORY", DropDownList1.SelectedItem.Value);
lblResult.Text = "You have selected this category. Please select a new category";
} else {
SqlCommand cmd1 = new SqlCommand("UPDATE SET CATEGORY CCID#CCID (CATEGORY, C_USERNAME, CCID) VALUES (#CATEGORY, #C_USERNAME, #CCID)", con);
cmd1.Parameters.AddWithValue("CATEGORY", DropDownList1.SelectedItem.Value);
cmd1.Parameters.AddWithValue("C_USERNAME", Session["id"]);
cmd1.Parameters.AddWithValue("CCID", Label1.Text);
int i = cmd1.ExecuteNonQuery();
if (i != 0) {
Label2.Text = " Your data is been saved in the database";
Label2.ForeColor = System.Drawing.Color.ForestGreen;
} else {
Label2.Text = "Something went wrong with selection";
Label2.ForeColor = System.Drawing.Color.Red;
}
}
con.Close();
}
}
Now let's discuss this line
string query = "SELECT CATEGORY FROM CATEGORY WHERE C_UserName = '" + Session["id"] + "' AND CATEGORY = '" + DropDownList1.SelectedItem.Value + "' ";
This let's attacker manipulate your input with sql injection. To solve this, use the same cmd1.Parameters.AddWithValue("CATEGORY", DropDownList1.SelectedItem.Value); that you are using in the second query. The Session["id"] is somewhat safer as it is not provided by the user but better safe than sorry as the parameters sanitize the input and protect you from sql injection.

Invalid attempt to call read when reader is closed when inserting data

i have a button that when clicked inserts data from textbox and combobox fields into database tables, but every time i insert it gives me "Invalid attempt to call read when reader is closed". How can i get rid of this error. And tips on optimising the code are welcome, because i know im a total noob. thanks
private void btnSave_Click(object sender, RoutedEventArgs e)
{
try
{
SqlConnection sqlCon = new SqlConnection(#"Data Source=(localdb)\mssqllocaldb; Initial Catalog=Storagedb;");
sqlCon.Open();
string Query1 = "insert into location(Storage, Shelf, columns, rows) values(" + txtWarehouse.Text + ", " + txtShelf.Text + ", " + txtColumn.Text + ", " + txtRow.Text + ")";
SqlCommand sqlCmd = new SqlCommand(Query1, sqlCon);
SqlDataAdapter dataAdp = new SqlDataAdapter(sqlCmd);
dataAdp.SelectCommand.ExecuteNonQuery();
sqlCon.Close();
}
catch (Exception er)
{
MessageBox.Show(er.Message);
}
try
{
SqlConnection sqlCon = new SqlConnection(#"Data Source=(localdb)\mssqllocaldb; Initial Catalog=Storagedb;");
sqlCon.Open();
string Query3 = "SELECT LOCATION_ID FROM LOCATION WHERE storage='" + txtWarehouse.Text + "' AND shelf='" + txtShelf.Text + "' AND columns='"
+ txtColumn.Text + "' AND rows='" + txtRow.Text + "'";
SqlCommand sqlCmd1 = new SqlCommand(Query3, sqlCon);
SqlDataReader dr = sqlCmd1.ExecuteReader(); ;
while (dr.Read())
{
string LocationId = dr[0].ToString();
dr.Close();
string Query2 = "insert into product(SKU, nimetus, minimum, maximum, quantity,location_ID,category_ID,OrderMail_ID) values ('" + txtSku.Text + "','" + txtNimetus.Text + "', '"
+ txtMin.Text + "', '" + txtMax.Text + "', '" + txtQuan.Text + "', '" + LocationId + "', '" + (cbCat.SelectedIndex+1) + "', '" + (cbMail.SelectedIndex+1) + "')";
SqlCommand sqlCmd = new SqlCommand(Query2, sqlCon);
SqlDataAdapter dataAdp = new SqlDataAdapter(sqlCmd);
dataAdp.SelectCommand.ExecuteNonQuery();
}
sqlCon.Close();
}
catch (Exception ed)
{
MessageBox.Show(ed.Message);
}
}
Let's try to make some adjustments to your code.
First thing to consider is to use a parameterized query and not a
string concatenation when you build an sql command. This is mandatory
to avoid parsing errors and Sql Injections
Second, you should encapsulate the disposable objects in a using statement
to be sure they receive the proper disposal when you have finished to
use them.
Third, you can get the LOCATION_ID from your table without running a
separate query simply adding SELECT SCOPE_IDENTITY() as second batch to your first command. (This works only if you have declared the LOCATION_ID field in the first table as an IDENTITY column)
Fourth, you put everything in a transaction to avoid problems in case
some of the code fails unexpectedly
So:
SqlTransaction tr = null;
try
{
string cmdText = #"insert into location(Storage, Shelf, columns, rows)
values(#storage,#shelf,#columns,#rows);
select scope_identity()";
using(SqlConnection sqlCon = new SqlConnection(.....))
using(SqlCommand cmd = new SqlCommand(cmdText, sqlCon))
{
sqlCon.Open();
using( tr = sqlCon.BeginTransaction())
{
// Prepare all the parameters required by the command
cmd.Parameters.Add("#storage", SqlDbType.Int).Value = Convert.ToInt32(txtWarehouse.Text);
cmd.Parameters.Add("#shelf", SqlDbType.Int).Value = Convert.ToInt32(txtShelf.Text);
cmd.Parameters.Add("#columns", SqlDbType.Int).Value = Convert.ToInt32(txtColumn.Text );
cmd.Parameters.Add("#rows", SqlDbType.Int).Value = Convert.ToInt32(txtRow.Text);
// Execute the command and get back the result of SCOPE_IDENTITY
int newLocation = Convert.ToInt32(cmd.ExecuteScalar());
// Set the second command text
cmdText = #"insert into product(SKU, nimetus, minimum, maximum, quantity,location_ID,category_ID,OrderMail_ID)
values (#sku, #nimetus,#min,#max,#qty,#locid,#catid,#ordid)";
// Build a new command with the second text
using(SqlCommand cmd1 = new SqlCommand(cmdText, sqlCon))
{
// Inform the new command we are inside a transaction
cmd1.Transaction = tr;
// Add all the required parameters for the second command
cmd1.Parameters.Add("#sku", SqlDbType.NVarChar).Value = txtSku.Text;
cmd1.Parameters.Add("#nimetus",SqlDbType.NVarChar).Value = txtNimetus.Text;
cmd1.Parameters.Add("#locid", SqlDbType.Int).Value = newLocation;
.... and so on for the other parameters required
cmd1.ExecuteNonQuery();
// If we reach this point the everything is allright and
// we can commit the two inserts together
tr.Commit();
}
}
}
}
catch (Exception er)
{
// In case of exceptions do not insert anything...
if(tr != null)
tr.Rollback();
MessageBox.Show(er.Message);
}
Notice that in the first command I use parameters of type SqlDbType.Int because you haven't used single quotes around your text. This should be verified against the real data type of your table columns and adjusted to match the type. This is true as well for the second command where you put everything as text albeit some of those fields seems to be integer (_location_id_ is probably an integer). Please verify against your table.

Error in gridviewUpdating asp.net with a timestamp update

I have two buttons, SetIn and SetOut. They both have the commandName UPDATE ( I have two buttons as I'd like the text to be different on the button depending on the value of one field in the row.
I'm getting a problem in that when I run the update SQL statement, it throws an error at me. It says:
An exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll but was not handled in user code
Additional information: Incorrect syntax near '14'.
This means that there is an issue with the date and time stamp that I am trying to update the row with (I'm making the update at 14.02pm).
My aspx.cs page code is:
protected void GridView1_RowUpdating(object sender, System.Web.UI.WebControls.GridViewUpdateEventArgs e)
{
Label id = GridView1.Rows[e.RowIndex].FindControl("lbl_Index") as Label;
int rowToUpdate = Int32.Parse(id.Text);
con = new SqlConnection(cs);
int scopeValue;
con = new SqlConnection(cs);
cmd = new SqlCommand();
cmd.CommandText = "SELECT in_scope FROM " + databaseName + " WHERE id = '" + rowToUpdate + "'";
cmd.Parameters.AddWithValue("#id", rowToUpdate);
cmd.Connection = con;
try
{
con.Open();
scopeValue = Convert.ToInt32(cmd.ExecuteScalar());
//database_entries.Text = recordCount.ToString();
}
finally
{
con.Close();
}
string modifiedBy = userManagement.getWeldID();
string updateDate = DateTime.UtcNow.ToString("dd/MMM/yyyy HH:mm:ss");
{
if (scopeValue == 1)
{
// Label id = GridView1.Rows[e.RowIndex].FindControl("lbl_Index") as Label;
string sqlStatement = "";
con = new SqlConnection(cs);
// SqlCommand cmd = new SqlCommand();
sqlStatement = #"update dbo.Fair_Use_InScope_MIF_Alex_temp set in_scope = '0', modified_by = " + modifiedBy + ", date_updated = " + updateDate + " where id = '" + rowToUpdate + "'";
con.Open();
cmd = new SqlCommand(sqlStatement, con);
cmd.ExecuteNonQuery();
con.Close();
ShowData();
}
if (scopeValue == 0)
{
// Label id = GridView1.Rows[e.RowIndex].FindControl("lbl_Index") as Label;
string sqlStatement = "";
con = new SqlConnection(cs);
// SqlCommand cmd = new SqlCommand();
sqlStatement = #"update dbo.Fair_Use_InScope_MIF_Alex_temp set in_scope = '1', modified_by = " + modifiedBy + ", date_updated = " + updateDate + " where id = '" + rowToUpdate + "'";
con.Open();
cmd = new SqlCommand(sqlStatement, con);
cmd.ExecuteNonQuery();
con.Close();
ShowData();
}
}
}
I'm basically trying to get the scopeValue (0 or 1) of the row, and if the Update command is called, and the scopeValue was previously 0, set it to 1 now and vice versa. I also need to update the time that the change was made and who made the change in that row. (these are both displayed in the gridview)
Any help would be much appreciated as I am a beginner to ASP.NET and C# and SQL SERVER!!
You are sending a DateTime as a string (without even enclosing single quotes date_updated = '" + updateDate + "') and that will always cause problems.
It's better to use parameters in your query. This prevents SQL injection, improves readability, ensures type safety, no more worries about the correct use of quotation marks etc.
string sqlStatement = "UPDATE dbo.Fair_Use_InScope_MIF_Alex_temp SET in_scope = 0, modified_by = #modifiedBy, date_updated = #updateDate WHERE (id = #rowToUpdate)";
using (SqlConnection connection = new SqlConnection(cs))
using (SqlCommand command = new SqlCommand(sqlStatement, connection))
{
command.Parameters.Add("#modifiedBy", SqlDbType.VarChar).Value = modifiedBy;
command.Parameters.Add("#updateDate", SqlDbType.DateTime).Value = DateTime.Now;
command.Parameters.Add("#rowToUpdate", SqlDbType.Int).Value = 35;
connection.Open();
command.ExecuteNonQuery();
}

Want to create a comment system in asp.net

i am coding for a commenting system in asp.net C# but i am stopped at delete command because of i am not using any type of serial numbers to comments posted, then how can i able to delete a specific comment, i am just using a username, date, time, and text in comment. Can anyone help me please that how to use a delete command in this condition??
here is my code for posting:
protected void pospost_Click(object sender, EventArgs e)
{
string login;
if (HttpContext.Current.Session["UserName"] != null)
{
login = HttpContext.Current.Session["UserName"].ToString();
con.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = "select * from mobiles_pos";
da = new SqlDataAdapter(cmd);
ds = new DataSet();
da.Fill(ds);
DataRow rw = ds.Tables[0].NewRow();
rw[0] = Model.Text.ToString();
rw[1] = titlepos.Text.ToString();
rw[2] = txtpos.Text.ToString();
rw[3] = DateTime.Today.Date.ToString();
rw[4] = DateTime.Now.TimeOfDay.ToString();
rw[5] = login.ToString();
ds.Tables[0].Rows.Add(rw);
SqlCommand cmd1 = new SqlCommand();
cmd1.Connection = con;
cmd1.CommandText = "insert into mobiles_pos values('" + Model.Text + "','" + titlepos.Text + "','" + txtpos.Text + "','" + DateTime.Today.Date + "','" + DateTime.Now.TimeOfDay + "','" + login + "')";
da.InsertCommand = cmd1;
da.Update(ds);
con.Close();
titlepos.Text = "";
txtpos.Text = "";
//DataList2.DataSource = ds;
//DataList2.DataBind();
BindDataList2();
}
}
Best - Add a Primary key to the "mobiles_pos" table since your using sql just use an identity field it will auto increment for you.
or
Quick - Use a combination of the User name and date comment was intered you must use the full date time or it will delete everything that user entered that day.
"Delete from mobiles_pos where username = #UserName and createdDate = #createdDate"

Datagrid filter in c# using sql server

How to filter data in datagrid for example if you select the combo box in student number then input 1001 in the text field. All records in 1001 will appear in datagrid. I am using sql server
private void button2_Click(object sender, EventArgs e)
{
if (cbofilter.SelectedIndex == 0)
{
string sql;
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Server= " + Environment.MachineName.ToString() + #"\; Initial Catalog=TEST;Integrated Security = true";
SqlDataAdapter da = new SqlDataAdapter();
DataSet ds1 = new DataSet();
ds1 = DBConn.getStudentDetails("sp_RetrieveSTUDNO");
sql = "Select * from Test where STUDNO like '" + txtvalue.Text + "'";
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.CommandType = CommandType.Text;
da.SelectCommand = cmd;
da.Fill(ds1);
dbgStudentDetails.DataSource = ds1;
dbgStudentDetails.DataMember = ds1.Tables[0].TableName;
dbgStudentDetails.Refresh();
}
else if (cbofilter.SelectedIndex == 1)
{
//string sql;
//SqlConnection conn = new SqlConnection();
//conn.ConnectionString = "Server= " + Environment.MachineName.ToString() + #"\; Initial Catalog=TEST;Integrated Security = true";
//SqlDataAdapter da = new SqlDataAdapter();
//DataSet ds1 = new DataSet();
//ds1 = DBConn.getStudentDetails("sp_RetrieveSTUDNO");
//sql = "Select * from Test where Name like '" + txtvalue.Text + "'";
//SqlCommand cmd = new SqlCommand(sql,conn);
//cmd.CommandType = CommandType.Text;
//da.SelectCommand = cmd;
//da.Fill(ds1);
// dbgStudentDetails.DataSource = ds1;
//dbgStudentDetails.DataMember = ds1.Tables[0].TableName;
//ds.Tables[0].DefaultView.RowFilter = "Studno = + txtvalue.text + ";
dbgStudentDetails.DataSource = ds.Tables[0];
dbgStudentDetails.Refresh();
}
}
It's difficult to answer pricisely to a vague question. I guess that you'll have to adapt your SQL query with a WHERE statement containing the user input.
If 'student number' is selected in the combo box, query like this (numbers starting with):
SELECT id, name, number FROM students WHERE number LIKE #search + '%'
If 'student name' is selected, use another query (names containing):
SELECT id, name, number FROM students WHERE name LIKE '%' + #search + '%'
Please explain in what sense C# is concerned.
You don't say what is wrong with the code you commented out. You also don't say what type the Studno column is.
Have you tried something like:
ds1.Tables[0].DefaultView.RowFilter = "Studno = '" + txtvalue.text + "'";

Categories