i am having trouble inserting data in table in C# - c#

private void btn_view_Click(object sender, EventArgs e)
{
con.Open();
OleDbDataAdapter da = new OleDbDataAdapter("Select * from tbl_emp", con);
DataSet ds = new DataSet();
da.Fill(ds);
dgv_emptable.DataSource = ds.Tables[0];
con.Close();
}
private void btn_insert_Click(object sender, EventArgs e)
{
con.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.CommandText = "Insert into tbl_emp(emp_id,emp_name,emp_surname,designation_id,dept_id) Values(" + txt_id.Text + " , '" + txt_name.Text + "','" + txt_phone.Text + "'," + cmb_desigid.SelectedValue + ",'" + cmb_deptid.SelectedValue.ToString() +"')";
cmd.Connection = con;
cmd.ExecuteNonQuery();
MessageBox.Show("Record inserted");
con.Close();
}
private void Form1_Load(object sender, EventArgs e)
{
con.Open();
OleDbDataAdapter da = new OleDbDataAdapter("Select * from tbl_designation", con);
DataSet ds = new DataSet();
da.Fill(ds);
cmb_desigid.DataSource = ds.Tables[0];
cmb_desigid.DisplayMember = "designation_type";
cmb_desigid.ValueMember = "designation_id";
con.Close();
con.Open();
OleDbDataAdapter db = new OleDbDataAdapter("Select * from tbl_dept",con);
DataSet dm = new DataSet();
db.Fill(dm);
cmb_deptid.DataSource = dm.Tables[0];
cmb_deptid.DisplayMember = "dept_name";
cmb_deptid.ValueMember = "dept_id";
con.Close();
}
I have bound my database and I am writing an insert query to insert data in table but I get the same error at cmd.ExecuteNonQuery
no given parameters are given for required parameters.
I have checked thoroughly but can't seem to find the error
I have used textbox for emp_id,emmp_name,emp_surname,and two combo boxes for designation_id and dept_id.
the dept_id and designation_id are foreign key in tbl_emp. and i also have used the combo box property.So can anyone please tell what the error is and also if i have writtern the combo box code properly...

You need to get in the habit of using "parameterized queries" - those won't just protect your code from the #1 vulnerability out there - SQL injection - they'll also solve a lot of thorny issues with adding quotes etc. to string values.
Try this code:
private void btn_insert_Click(object sender, EventArgs e)
{
// define the insert query - OleDB uses unnamed, positional parameters
string insertQuery = "INSERT INTO tbl_emp (emp_id, emp_name, emp_surname, designation_id, dept_id) " +
"VALUES (?, ?, ?, ?, ?)";
// create command
OleDbCommand cmd = new OleDbCommand(insertQuery, con);
// define parameters - in the proper order! - and set their values
// The "names" like "#emp_id" that I'm using here are just to make it easier for you to grasp which parameter
// corresponds to which columns being inserted - you could also name them "p1", "p2" etc. - not very intuitive, though ...
// Check the *assumptions* I made for the datatypes - not sure if those are
// really what you have - adapt as needed
cmd.Parameters.Add("#emp_id", OleDbType.Int).Value = Convert.ToInt32(txt_id.Text);
cmd.Parameters.Add("#emp_name", OleDbType.VarChar, 100).Value = txt_name.Text;
cmd.Parameters.Add("#emp_surname", OleDbType.VarChar, 100).Value = txt_phone.Text
cmd.Parameters.Add("#designation_id", OleDbType.Int).Value = cmb_desigid.SelectedValue;
cmd.Parameters.Add("#dept_id", OleDbType.Int).Value = cmb_deptid.SelectedValue;
// open connection, execute query, close connection
con.Open();
cmd.ExecuteNonQuery();
con.Close();
MessageBox.Show("Record inserted");
}
As a general side note: if you're only ever interested in a single DataTable being returned from a query - I'd strongly recommend using this code (instead of what you have now):
private void Form1_Load(object sender, EventArgs e)
{
con.Open();
OleDbDataAdapter da = new OleDbDataAdapter("Select * from tbl_designation", con);
// define and use a "DataTable" - not a "DataSet" (which is overkill for just a single table of data)
DataTable dt = new DataTable();
da.Fill(dt);
cmb_desigid.DataSource = dt;
cmb_desigid.DisplayMember = "designation_type";
cmb_desigid.ValueMember = "designation_id";
con.Close();

I mentioned in the comments that you can get VS to do all this for you, in less time, and more securely/reliably than a human could do in a day. Writing db access code is boring and annoying, here's how you hand it off:
add a new dataset to the project, just like you would add a form or class or any other thing. Call it something sensible, not dataset1
open the server explorer window, and add a connection to your access db
drag the db into the dataset. Thoroughly read the long message box that pops up. No one reads this, and they should read it. It solves a lot of confusion later on when the build process is overwriting the database the exe is saving in, and it looks like your app never saves any data. Click yes
drag some tables out of the server explorer and into the dataset. Not the appearance of a datatabke with all the same columns as your db table and a tableadapter. This thing is NOT your database table, it is a strongly typed client side datatable which is a better version of what you're doing in your code above with weakly typed datasets and datatables. A tableadapter is a better version of a dataadapter designed to work with the better datatable it is visually attached to
switch to the forms designed
open the data sources window from the view menu, other windows submenu
drag one of the nodes out of data sources and onto the form
Many things appear, a data grid view, binding source, navigator, dataset, tableadapter, manager. Don't delete stuff until you understand how it all works because it will teach you a lot. Run the program
This app will work, load data, save data and you didn't so far write any code at all. VS wrote all the code for you and you can read it if you want, it's there in the .Designer.cs files on disk
Run the app, add some rows, change stuff, click save, close the app. Don't run the app again yet, but instead go into the bin/debug folder and open that db on there, in access. See your data you added/changed
Now close access and build the project again, now open the same bin/debug db in access.. see the data has gone? The build process copied the blank db from the project over the top of the db the exe altered when it ran. Make sure you grok what is happening here every time you build or you'll be very confused as to why your app "isn't saving" (it is, but the changes are being wiped by the build process)
Some other things you need to know about tableadapters:
they can have more than one select command- just right click them in the dataset designer and add another query. Use parameters, like SELECT * FROM t WHERE id = #id and give the command a sensible name like FillById. The tableadapter will gain a method myTabkeAdapter.FillById(someDatatableHere, 1234) to fill that datatable with row ID 1234
they have an Update method that takes a datatable. This is NOT JUST for running update queries. Update scans the whole passed on datatable looking for rows that need to be inserted updated or deleted and executes the relevant sql. When you change a datatable row, the change is tracked by the RowState property. If the rowstate is Added, and insert will be run by the table adapter, to insert the row. If the rowstate is Modified, an Update will be run. If the rowstate is deleted, a delete will be run. Microsoft should have called Update something else, like Save, because it causes confusion often

Related

DataGridView not showing table C#

My data grid view isn't showing the data. I want it to show whole table at runtime and a search option to search specific rows.
SqlConnection con = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\DELL\source\repos\phoneBookwin\phoneBookwin\Database1.mdf;Integrated Security=True");
con.Open();
using (SqlCommand com = new SqlCommand("select * from Contacts"))
{
using (SqlDataAdapter db = new SqlDataAdapter("select * from Contacts", con))
{
DataTable View = new DataTable();
db.Fill(View);
}
}
and this is for searching specific contact
private void search_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\DELL\source\repos\phoneBookwin\phoneBookwin\Database1.mdf;Integrated Security=True");
con.Open();
SqlDataAdapter cmd = new SqlDataAdapter("Select * from Contacts where Name = '"+searchBox.Text+"'",con);
DataTable View = new DataTable();
cmd.Fill(View);
con.Close();
}
The data gridview isn't showing anything whether I click the search button or not.
Your code never assigns the resulting DataTable you filled, to a datagridview; it just fills it then throws it away. You need a call to someDataGridView.DataSource = View after the call to Fill
If, after you do this the datagridview is still blank, it is likely no data was downloaded to the datatable. Check you're connected to the correct database and that the table has data. If you don't see the columns you expect, check that the datagridview's AutoGenerateColumns setting is true
Other points, please ..
..stop writing SQL in the way you currently are, concatenating the value in from a textbox - not only will it fall sort of someone searches for the name O'Connor it also puts you at risk of the most common form of hacking applicable to database software. Read http://Bobby-tables.com - your code should look more like:
using(var da = new SqlAdapter("SELECT * FROM t WHERE c LIKE #p") {
da.SelectCommand.Parameters.Add("#p", SqlDbType.VarChar, 4000).Value = textbox.Text;
//fill etc
}
..make yourself familiar with C# naming conventions. View should be called view because it is a local member, not a publicly accessible class level property
There are a number of issues with your example the primary issue is what you are not yet assigning the table as a source to a Grid as mentioned by Calus Jard.
Additionally, your query with user input being concatenated into a SQL query is very dangerous, I would recommend using a parameter

Issue while showing result of a query from database to DataGridView

working with an assignment here i am able to view all data from database to grid view but the data appears to be unsorted and it displays all data i only want to display the result of a query in the DataGridView the code i have tried is :
private void btnmeritbsit_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(dbpath);
string query = "select Applicant_no,A_Name,Father_Name,T_Matric,O_Matric,M_Percentage,T_Inter ,O_Inter ,I_Percentage from applicantinfo order by I_Percentage desc";
con.Open();
dataGridView1.ColumnCount = sdr.FieldCount;
SqlCommand cmd = new SqlCommand(query, con);
SqlDataReader sdr = cmd.ExecuteReader();
while (sdr.Read())
{
dataGridView1.Rows.Add(sdr["Applicant_no"], sdr["A_Name"], sdr["Father_Name"], sdr["T_Matric"], sdr["O_Matric"], sdr["M_Percentage"], sdr["T_Inter"], sdr["O_Inter"], sdr["I_Percentage"]);
}
con.Close();
}
i was getting the whole values through datatable and dataAdapter but nothing works !!stuck!!
// DataTable dtbl = new DataTable();
// sda.Fill(dtbl);
// dataGridView1.DataSource = dtbl;
What I wrote in the other answer, in pictures. This is using a VB app, but it doesn't matter because the steps are the same and you're not actually going to be writing much more than one line of code
Right click project, add new dataset
Right click surface, add tableadapter
Add a connection string, Next. Name it, Next
Add a query that selects all from your table, WHERE (id column) = #id
Rename the methods to add "ByID". It will be obvious why later. Finish:
Right click table adapter, Add Query
Proceed through choosing "Select that returns rows" and entering a query that seeks users by last name:
Give good names to the new methods. Finish. Save:
Go to the forms designer, make sure Data Sources tool panel is showing (View Menu)
Drag the Users grid node from Data Sources onto the form
It has pre-made a textbox for the ID, because that's the first query in the tableadapter. We'll change it to lastname. Click the button, change its name, change the text it shows. Always make sure your control names are up to date and relevant.
You can see I changed the label too, and I also changed the name of the textbox (you can't see it) and I changed the name of everything in the tray under the designer, so it starts with underscore:
I do this because VB is case insensitive and calling variable the same name as their type is a bad idea in any language, and makes intellisense confusing in VB. You don't have to add the leading underscores in C#. It's enough to discriminate on case alone, though arguably not always wise:
Now we need to change the code. Double click the FillBy button. It goes to code. Maybe you have some code already, maybe not. Make sure the code fills the table using the relevant input. This is the only part of the process that really requires you to think about what you're doing and what your variables are called (they may be different to mine)
The code probably defaulted to saying
_usersTableAdapter.FillByID(_myDataSet.Users, new Guid(_lastNameToolStripTextBox.Text));
Because it used to be set up for you to type an id (guid or int, my db has a guid) in that box but we have changed it for lastname. So we need to change the FillByID (and now you see why we give them sensible names, not FillBy1 and FillBy2) so it's FillByLastName, and we need to change the code so we pass a string lastname, not a guid ID
_usersTableAdapter.FillByLastName(_myDataSet.Users, _lastNameToolStripTextBox.Text);
That's the only code you have to write. Remember I named my things on the form using leading underscores, so my code has leading underscores. If you dont rename your things, your code won't have leading underscores
Now run the app:
Look at all those John Smiths! They are different users, of course - the ID is different for every one. You can even write new details in here and press save to update the db..
From one line of code! :)
this works perfectly fine just after a few changes :)
private void btnmeritbscs_Click(object sender, EventArgs e)
{
string dbpath = #"Data Source=DESKTOP-UMA0VFO;Initial Catalog=ApplicationForm;Integrated Security=True";
SqlConnection con = new SqlConnection(dbpath);
string query = "select prgstatus,Applicant_no,A_Name,Father_Name,T_Matric,O_Matric,M_Percentage,T_Inter ,O_Inter ,I_Percentage from applicantinfo where prgstatus like 'bscs' order by I_Percentage desc";
SqlCommand cmd = new SqlCommand(query, con);
con.Open();
SqlDataReader sdr = cmd.ExecuteReader();
dataGridView1.ColumnCount = sdr.FieldCount;
while (sdr.Read())
{
dataGridView1.Rows.Add(sdr["prgstatus"], sdr["Applicant_no"], sdr["A_Name"], sdr["Father_Name"], sdr["T_Matric"], sdr["O_Matric"], sdr["M_Percentage"], sdr["T_Inter"], sdr["O_Inter"], sdr["I_Percentage"]);
}
con.Close();
}

SQL Server CE WHERE statement behaving wrong? very confused

I am developing a windows mobile app. Right now I am just testing that it can correctly query the local SQL Server CE database. It works fine until I put a WHERE statement in.
Here is my code:
private void buttonStart_Click(object sender, EventArgs e)
{
System.Data.SqlServerCe.SqlCeConnection conn = new System.Data.SqlServerCe.SqlCeConnection(
("Data Source=" + (System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase), "ElectricReading.sdf") + ";Max Database Size=2047")));
try
{
// Connect to the local database
conn.Open();
System.Data.SqlServerCe.SqlCeCommand cmd = conn.CreateCommand();
SqlCeParameter param = new SqlCeParameter();
param.ParameterName = "#Barcode";
param.Value = "%" + textBarcode.Text.Trim() + "%";
// Insert a row
cmd.CommandText = "SELECT * FROM Main2 WHERE Reading LIKE #Barcode";
cmd.Parameters.Add(param);
cmd.ExecuteNonQuery();
DataTable data = new DataTable();
using (SqlCeDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
data.Load(reader);
}
}
if (data != null)
{
this.dataGrid1.DataSource = data;
}
}
finally
{
conn.Close();
}
The database contains this data:
Okay so you can see I changed the WHERE statement to use the Reading column just for testing purposes. When I enter "111" into the textbox and run --> it returns only the row where reading ="1111" and not the row that contains "111".
If I enter "1111" it does not return any data.
If I enter "1" it will return both the "1111" row and the "111" row which is the correct behavior.
However if I enter "11" it once again only returns the "1111" row.
Any other data entry of 2's or 9's attempting to return those rows does not work.
I'm not sure what is going on? This does not make any sense. It is not behaving like I would expect in any way shape or form. I know this must be a little confusing to read. I hope it makes enough sense to get some answers. Please help!
NOTE: I added the "%" before and after the text in an attempt to get better results. This is not desired.
EDIT <<<-----------------------I did have Reading = #Barcode, I just accidently typed Location for this question, that is not the problem.
Firstly, some things to note:
1) As other commentators have noted, use the Reading column, not the Location column. I know you have mentioned you are testing, but swapping around column names and then changing code isn't the easiest way to troubleshoot these things. Try to only change one thing at a time.
2) If Reading is numeric, you are going to have to convert the column value first.
So your query becomes:
"SELECT * FROM Main2 WHERE CONVERT(varchar, Reading) LIKE #Barcode";
Also see How to use parameter with LIKE in Sql Server Compact Edition for more help with working with parameters in SqlServerCE.
3) Set a parameter type on your SqlCEParameter. I've linked to the appropriate page in the code example below.
4) You are using ExecuteNonQuery for no reason. Just get rid of it in this context. It's for when you want to make a change to the database (like an insert, update, delete) or execute something (like a stored proc that can also insert, update, delete etc) that returns no rows. You've probably cut and paste this code from another place in your app :-)
5) Use using on disposable objects (see example below). This will make managing your connection lifecycle much simpler. It's also more readable (IMO) and will take care of issues when exceptions occur.
6) Use the using statement to import the BCL (Base Class Libraries) into your current namespace:
Add the following using statements to the top of your class (.cs). This will make using all of the .Net classes a lot simpler (and is much easier to read and less wear on your keyboard ;-)
using System.Data.SqlServerCe;
using System.IO;
using System.Reflection;
A more complete example would look like the following
private void buttonStart_Click(object sender, EventArgs e)
{
using(SqlCeConnection conn = new SqlCeConnection(
("Data Source=" + (Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase), "ElectricReading.sdf") + ";Max Database Size=2047"))))
{
// Connect to the local database
conn.Open();
using(SqlCeCommand cmd = conn.CreateCommand())
{
SqlCeParameter param = new SqlCeParameter();
param.ParameterName = "#Barcode";
param.DBType = DBType.String; //Intellisense is your friend here but See http://msdn.microsoft.com/en-US/library/system.data.sqlserverce.sqlceparameter.dbtype(v=VS.80).aspx for supported types
param.Value = "%" + textBarcode.Text.Trim() + "%";
// SELECT rows
cmd.CommandText = "SELECT * FROM Main2 WHERE CONVERT(varchar, Reading) LIKE #Barcode";
cmd.Parameters.Add(param);
//cmd.ExecuteNonQuery(); //You don't need this line
DataTable data = new DataTable();
using (SqlCeDataReader reader = cmd.ExecuteReader())
{
data.Load(reader); //SqlCeDataReader does not support the HasRows property.
if(data.Rows.Count > 0)
{
this.dataGrid1.DataSource = data;
}
}
}
}
}
Intellisense should be able to clean up any errors with the above but feel free to ask for more help.
Finally, you also might be able to set the data source of the grid directly to a datareader, try it!
using (SqlCeDataReader reader = cmd.ExecuteReader())
{
dataGrid1.DataSource = reader;
}
You can then get rid of the DataTable.
Change the following line:
cmd.CommandText = "SELECT * FROM Main2 WHERE Location LIKE #Barcode";
to
cmd.CommandText = "SELECT * FROM Main2 WHERE Reading LIKE #Barcode";
You are comparing the wrong columns.

How can we use two queries in same click event?

I used the code:
protected void Button1_Click(object sender, EventArgs e)
{
DataSet ds = new DataSet();
SqlConnection con = new SqlConnection("server=kiran-b946c0f6d;
uid=sa;
pwd=123;
database=employe");
SqlCommand com=new SqlCommand("INSERT INTO Emplo VALUES('"+TextBox2.Text+"'",con);
com.Parameters.Add("Email_ID", SqlDbType.VarChar);
com.Parameters["Email_ID"].Value = TextBox2.Text;
con.Open();
Label3.Text = "successfully added";
SqlDataReader reader = null;
com = new SqlCommand("SELECT Email_ID FROM Emplo WHERE Email_ID='"
+ TextBox2.Text + "'",
con);
reader = com.ExecuteReader();
if (reader != null && reader.HasRows)
{
Label3.Text = "Emailid alraedy exist";
}
reader.Dispose();
SqlDataAdapter da = new SqlDataAdapter(com);
da.Fill(ds);
GridView1.DataSource = ds;
GridView1.DataBind();
con.Close();
}
I intended to use Insert values in the database and if there is any duplicity,it will show the error.The duplicity is working properly.But insertion is not properly working.It will show inserted successfully.But the values are not doing insertion.
You're not actually calling com.ExecuteNonQuery() before overwriting the com variable.
You aren't running the insert at all - you set up the command and then overwrite it with your new select command.
Even if you were running the insert at that point your select that is coming after it would always be expected to return true because you've just inserted it. Additionally depending on the database structure if that database field is set to be unique (which seems to be what you are trying to enforce in the code) then I would expect a sql exception to be thrown as you try to insert something which already exists.
What you want to do is run the select to check if it already exists first. Then if it exists you can just stop. If it doesn't exist you can do the insert then.
Or better still write a single SQL statement (better yet a procedure) that does the check at the same time as the insert to try to prevent any possible issues relating to two threads doign the check and finding it doesn't exist and then two threads doing the insert causing one of them to fail most likely.

Strongly-typed dataset: how to save data on db after adding data?

I know this is a silly question and I feel so stupid, but I can't find the right (the easy) way to accomplish my task.
I have an Access database imported in Visual Studio 2010 for a C# project: VS creates for me (thanks!!) strongly-typed dataset about my db. Well done.
Then, in my app, I create a new instance of this dataset CDS ds = new CDS(); and add records in its tables. Finally I do ds.AcceptChanges(); but nothing happens on db.
OK, I googled araound and think (realize?!?) I gotta open a db connection, create a DataAdapter and fill my dataset with this:
CDS ds = new CDS();
OleDbConnection conn = new OleDbConnection(path_to_db);
conn.Open();
OleDbDataAdapter da = new OleDbDataAdapter("SELECT * FROM mytable", conn);
da.Fill(ds.Editori); //Editori is a TableTable created automatically
// Insert rows in dataset
if (ds.HasChanges()) ds.AcceptChanges();
int ret = da.Update(ds.Editori);
Debug.Print("Update() returns: {0}", ret);
conn.Close();
but ret=0 and nothing happens on database, while in DS.Editori I have 106 rows!!
To complete my desperation: table mytable has an auto increment field as primary key; when I load ds with da, this field is correct for every record, but when I insert rows on ds, records have -1, -2, -3, etc... Why?
Can someone tells me the right way to work with strongly-typed datasets?
I gonna study, read books, I promise, but now I'm late for this job...
Thanks
UPDATE:
As suggested from Dev-Express I created the insert command, but the result is the same: when I update da, nothing happens on db.
OleDbCommand cmd = new OleDbCommand(
"INSERT INTO Editori (ID,Editore) VALUES(?,?)", conn);
cmd.Parameters.Add("#ID", OleDbType.Integer);
cmd.Parameters.Add("#Editore", OleDbType.VarChar, 255, "Editore");
da.InsertCommand = cmd;
int ret = da.Update(ds.Editori);
Debug.Print("Update() returns: {0}", ret);
conn.Close();
ANOTHER UPDATE:
I solved problem with primary keys: in generated class I manually had to change all of these lines:
this.columnID.AutoIncrementSeed = 1; // It was -1
this.columnID.AutoIncrementStep = 1; // It was -1
If you created a strongly typed DataSet using the Visual Studio designer, there will be a TableAdapters in the dataset or TableManager created for that DataSet.
MSDN gives the following example for usage:
NorthwindDataSet northwindDataSet = new NorthwindDataSet();
NorthwindDataSetTableAdapters.CustomersTableAdapter customersTableAdapter =
new NorthwindDataSetTableAdapters.CustomersTableAdapter();
//Fill from database
customersTableAdapter.Fill(northwindDataSet.Customers);
//... changes to table
//Save changes to database
customersTableAdapter.Update(northwindDataSet.Customers);
Alternatively if your Visual Studio designer created a TableManager:
NorthwindDataSet northwindDataSet = new NorthwindDataSet();
TableAdapterManager northwindTableManager = new TableAdapterManager();
//Fill from database
northwindTableManager.CustomersTableAdapter.Fill(northwindDataSet.Customers);
//... changes to table
//Save changes to database
northwindTableManager.CustomersTableAdapter.Update(northwindDataSet.Customers);
You should also specify the UpdateCommand of the OleDBDataAdapter and then execute it by calling the da.Update method. There is an example of how this can be done in the MSDN:
OleDbDataAdapter.OleDbDataAdapter(String, OleDbConnection) Constructor

Categories

Resources