My primary key is not getting updated - c#

When I tried to update my primary key from the textbox, it's not getting updated. The rest of the columns are updated fine. Please help me.
I am not getting any error. Nothing.. When I try to update the part number.. it's not updating.. Simply going back to the previous value.
My code to update value to database:
private void Update_Click(object sender, EventArgs e)
{
try
{
SqlConnection con = new SqlConnection(#"Data Source=SREEJITHMOHA492\SQLEXPRESS;Initial Catalog=cndb;Integrated Security=True");
con.Open();
SqlCommand cmd = new SqlCommand(#"update cncinfo set part='" + this.file_NameTextBox.Text
+ "',drawings='" + this.drawingsTextBox.Text + "',draftpath='"
+ this.gcodeTextBox.Text + "',comments='" + this.commentsTextBox.Text
+ "' where part='" + dataGridView1.Rows[0].Cells[0].Value.ToString() + "' ;", con);
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
}
}
void load_table()
{
SqlConnection con = new SqlConnection(#"Data Source=SREEJITHMOHA492\SQLEXPRESS;Initial Catalog=cndb;Integrated Security=True");
con.Open();
SqlCommand cmd = new SqlCommand("select part as 'Part Number',drawings as 'Drawings',draftpath as 'G-Code Path',releasepath as 'Release Path',comments as 'Comments' from cncinfo ;", con);
cmd.ExecuteNonQuery();
con.Close();
try
{
SqlDataAdapter sda = new SqlDataAdapter();
sda.SelectCommand = cmd;
dbddataset = new DataTable();
sda.Fill(dbddataset);
BindingSource bSource = new BindingSource();
bSource.DataSource = dbddataset;
dataGridView1.DataSource = bSource;
sda.Update(dbddataset);
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Thanks in advance

First, use parameters. See Bobby Tables.
Second, your update statement uses the same input for both the set and where clauses:
#"update cncinfo set part='" + this.file_NameTextBox.Text + "',...' where part='" + this.file_NameTextBox.Text + "' ;"
How do you plan to change the value of the part when you select only the row that already has the new value? You need to use both an old and new value:
#"update cncinfo set part='" + this.file_NameTextBox.Text + "',...' where part='" + oldPart + "' ;"
Finally, ExecuteNonQuery returns the number of rows affected. If you checked the value you would find that it is 1 when you update a row and 0 when you try to change the value of part unless there is already a row with the new part value (in which case you update that row instead of generating an error on a duplicate part).
You should also consider using a using statement for your connections and commands.

Related

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.

delete and update the selected row

executenonquery is my problem, this code works on other button in different datagridview
here's my code at delete button
private void button4_Click_2(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(#"Data Source=XXYZZ\SQLEXPRESS;Initial Catalog=rick_inventiory;Integrated Security=True");
SqlCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "Delete from tbl_Orders where CustomersID2 = '" + dataGridView5.SelectedRows[0].Cells[0].Value.ToString() + "'";
con.Open();
cmd.Parameters.AddWithValue("#CustomerID2", txtCustomerID2.Text);
cmd.ExecuteNonQuery();
con.Close();
disp_data();
MessageBox.Show("Deleted Successfully");
}
the update code still execute sa code but did not update it
and heres my code for Update button
SqlConnection con = new SqlConnection(#"Data Source=XXYZZ\SQLEXPRESS;Initial Catalog=rick_inventiory;Integrated Security=True");
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "Update tbl_Products SET ProductName='" + txtProName.Text +
"',Stocks='" + txtStocks.Text + "',Price='" + txtPrice.Text + "',Description='" +
txtDesc.Text + "',CategoryName='" + txtCat.Text + "' where ProductID ='" + txtProID.Text + "';";
cmd.ExecuteNonQuery();
SqlDataAdapter da = new SqlDataAdapter("Select * from tbl_Products", con);
DataTable dt = new DataTable();
da.Fill(dt);
dataGridView1.DataSource = dt;
MessageBox.Show("Successfuly Updated");
con.close();
In update there is a syntax problem remove inner side semi colon of update query
While in delete you want to change the line
from
cmd.Parameters.AddWithValue("#CustomerID2", txtCustomerID2.Text);
to
cmd.Parameters.AddWithValue("#CustomerID2", '" + dataGridView5.SelectedRows[0].Cells[0].Value.ToString() + "');

eliminating duplicate records insertion into database

The below is my code to insert gridview data into a database. However, using this I want to check and restrict insertion into the database where records have the same name, location, education and salary. If all of these are the same and those already present in database they should not get inserted. If any one column is different then they should get inserted.
protected void btn_insert_Click(object sender, EventArgs e)
{
foreach (GridViewRow g1 in GridView1.Rows)
{
SqlConnection con = new SqlConnection(connStr);
cmd = new SqlCommand("insert command", con);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
UploadStatusLabel.Text = "Records Inserted Successfully";
}
I think hitting the database inside a for loop is a very bad idea when you have other options. I'm not tackling this issue in the below sample.
Your code may be subject to SQL Injection, you need to use parameters to pass your values. If someone filled the input with ";DROP TABLE OpenOfficetext;" and they have DROP permissions, it will be a problem if you're just concatenating strings.
To avoid duplicates, you can check first if a similar record exists.
foreach (GridViewRow g1 in GridView1.Rows)
{
string insertCommand = "insert into OpenOfficetext(Name, Location, Education, Salary) values(#p1, #p2, #p3, #p4)";
string selectCommand = "SELECT COUNT(*) FROM OpenOfficetext WHERE Name = #p1 AND Location = #p2 AND Education = #p3 AND Salary = #p4";
SqlConnection con = new SqlConnection(connStr);
SqlCommand cmd = new SqlCommand(selectCommand, con);
con.Open();
cmd.Parameters.AddWithValue("#p1", g1.Cells[0].Text);
cmd.Parameters.AddWithValue("#p2", g1.Cells[1].Text);
cmd.Parameters.AddWithValue("#p3", g1.Cells[2].Text);
cmd.Parameters.AddWithValue("#p4", g1.Cells[3].Text);
if (Convert.ToInt32(cmd.ExecuteScalar()) == 0)
{
cmd.CommandText = insertCommand;
cmd.ExecuteNonQuery();
}
con.Close();
}
please use the below code
if not exist (select * from OpenOfficetext where Name='" + g1.Cells[0].Text + "' and Location='" + g1.Cells[1].Text + "' and Education = '" + g1.Cells[2].Text + "' and Salary = '" + g1.Cells[3].Text + "' )
Begin
SqlConnection con = new SqlConnection(connStr);
cmd = new SqlCommand("insert into OpenOfficetext(Name,Location,Education,Salary) values ('" + g1.Cells[0].Text + "','" + g1.Cells[1].Text + "','" + g1.Cells[2].Text + "','" + g1.Cells[3].Text + "')", con);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
End

Can you help me to show datagridview and Refresh after update?

This is my code and error message when you running say:
An unhandled exception of type System.Data.SqlClient.SqlException
occurred in System.Data.dll
on this da.fill(dt);
SqlConnection con = new SqlConnection("Data Source=ANTONIANGGA-PC\\SQLEXPRESS;Initial Catalog=FullandStarving;Integrated Security=True");
SqlCommand cmd;
SqlDataAdapter da;
DataTable dt = new DataTable();
public FormProduksi()
{
InitializeComponent();
showgridview();
}
private void showgridview()
{
con.Open();
dt.Clear();
cmd = new SqlCommand("SELECT * FROM Produksi", con);
//cmd.CommandType = CommandType.StoredProcedure; done :D
da = new SqlDataAdapter(cmd);
da.Fill(dt);
dataGridView1.DataSource = dt;
con.Close();
}
private void button2_Click(object sender, EventArgs e)
{
//Datetimepicker to Database
string dProduksi = DateTime.Parse(dtmProduksi.Text).ToString("yyyy-MM-dd");
try{
con.Open();
cmd = new SqlCommand("insert into Produksi (IDProduksi,IDPhoto,TanggalProduksi,NamaKaryawan,KeteranganPhoto) Values('" + txtIdpro.Text + "','" + txtIdPhoto.Text + "','" + dProduksi + "','" + txtNamaKaryawan.Text + "','" + rxtKtrphoto.Text + "')", con);
cmd.ExecuteNonQuery();
MessageBox.Show("Update telah di jalankan");
showgridview();
clear();
con.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
that update successfully but cant refresh, so i do quit that form and open can see it
You are closing the connection
con.Close();
and then using
da.Fill(dt);
Just swap this lines:
showgridview();
con.Close();
For example with DbDataAdapter.Fill:
Notes:
1
Yoy should use parametrized queries so you avoid SQL Injection attacks:
var cmd = new SqlCommand("SELECT EmpName FROM Employee WHERE EmpID = #id", con);
cmd.Parameters.AddWithValue("#id", id.Text);
2
Wrap SqlConnection and SqlCommand into using so any resources used by those would disposed:
string position;
using (SqlConnection con = new SqlConnection("server=free-pc\\FATMAH; Integrated Security=True; database=Workflow; "))
{
con.Open();
using (var cmd = new SqlCommand("SELECT EmpName FROM Employee WHERE EmpID = #id", con))
{
cmd.Parameters.AddWithValue("#id", id.Text);
var name = cmd.ExecuteScalar();
if (name != null)
{
position = name.ToString();
Response.Write("User Registration successful");
}
else
{
Console.WriteLine("No Employee found.");
}
}
}
Credit
Just change the showgridview() function as below where connection is opened & closed properly.
Also check your sql query ,provide space and maintain syntax of query :
SELECT * FROM Produksi
Error screenshot clearly depicts that stored procedure with such name don't exist
comment out those lines as code below :
void showgridview()
{
con.Open();
dt.Clear();
cmd = new SqlCommand("SELECT * FROM Produksi", con);
//cmd.CommandType = CommandType.StoredProcedure;
da = new SqlDataAdapter(cmd);
da.Fill(dt);
dataGridView1.DataSource = dt;
con.Close();
}
Then you wont be having connection issues and errors related .
Button Click code change the closing connection as below:
private void button2_Click(object sender, EventArgs e)
{
//Datetimepicker to Database
string dProduksi = DateTime.Parse(dtmProduksi.Text).ToString("yyyy-MM-dd");
try
{
con.Open();
cmd = new SqlCommand("insert into Produksi (IDProduksi,IDPhoto,TanggalProduksi,NamaKaryawan,KeteranganPhoto) Values('" + txtIdpro.Text + "','" + txtIdPhoto.Text + "','" + dProduksi + "','" + txtNamaKaryawan.Text + "','" + rxtKtrphoto.Text + "')", con);
cmd.ExecuteNonQuery();
MessageBox.Show("Update telah di jalankan");
con.Close();
showgridview();
clear();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Also, for further reading:
parameterized queries vs. SQL injection
Why do we always prefer using parameters in SQL statements?

A problem in Updation of the record c#

i don't know why every time i perform update of my record, the query from which i update do not increments the ID from 0 to 1 and always it takes 0.. i don't know how do i increment my id to 1 and so far.. please explain.. :/ .. my code is :
private void btnUpdate_Click(object sender, EventArgs e)
{
int CustomerID =0;
SqlConnection cn = new SqlConnection(#"Data Source=COMPAQ-PC-PC\SQLEXPRESS;
Initial Catalog=Gym;Integrated Security=True");
SqlCommand cmd = new SqlCommand("Update Customer set Customer_Name = '" + tbName.Text + "',Cell_Number = '" + tbContactNumber.Text + "',Customer_Address = '" + tbAddress.Text + "' where CustomerID = " + CustomerID, cn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
BindGridView();
}
private void BindGridView()
{
SqlConnection cn = new SqlConnection(#"Data Source=COMPAQ-PC-PC\SQLEXPRESS;Initial Catalog=Gym;Integrated Security=True");
SqlCommand cmd = new SqlCommand("Select * from Customer", cn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
dgView_CustomerInfo.DataSource = dt.DefaultView;
}
You need to use Command.ExecuteNonQuery() instead.
Your really need to read a book about .net programming. Your code is full of glitches...
To get you started...
// put the connection string into the app.config
using (SqlConnection cn = new SqlConnection(#"Data Source=COMPAQ-PC-PC\SQLEXPRESS; Initial Catalog=Gym;Integrated Security=True"))
{
int result = new SqlCommand("Update Customer set Customer_Name = '" + tbName.Text + "',Cell_Number = '" + tbContactNumber.Text + "',Customer_Address = '" + tbAddress.Text + "' where CustomerID = " + CustomerID, cn).ExecuteNonQuery();
// eval result to see wether there was realy an updated record...
}
On a SqlConnection use the using() statement. That way the dispose of the object is taken care of. In fact use it on all objects that are disposable.
Try to use app.config / web.config for the connection string.
Escape all the user input that goes to the sql server to prevent sql-injection. http://de.wikipedia.org/wiki/SQL-Injection
You are using "Update Customer" sql clause.
That means that you are going to update EXISTING record, not to insert NEW one.
The ID is incrementing only for NEW records, but not for existing ones.
Also, make sure that your ID column is properly configured.
It should has IDENTITY(1,1)clause like in example below:
CREATE TABLE [dbo].[td_Component](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Url] [nvarchar](250) NOT NULL,
[Caption] [nvarchar](50) NOT NULL,
[Description] [varchar](4000) NULL,

Categories