Refresh SQLDataReader on button click - c#

Same as the title and using C#.
Anyone know how to do this? I have a bunch of data read into a list box but the data doesn't refresh unless I restart the windows form. anyone know how to refresh it on a button click event?
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = (#"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\John\Desktop\DB\DB\DB\setup.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True");
conn.Open();
SqlCommand cmd = new SqlCommand
("SELECT PEOPLE " + "FROM Workers", conn);
try
{
SqlDataReader sdr = cmd.ExecuteReader();
while (sdr.Read())
{
listBox1.Items.Add(sdr["people"].ToString());
}
sdr.Close();
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
finally
{
conn.Close();
}
}
This is in windows form Load. So i'm looking to add a button on my form which refreshes the listbox items list

Add a Method
private void ShowPeople()
{
// Put your code;
}
and then use the same in your button click
private void Button_Click(object sender,EventArgs e)
{
ShowPeople();
}

To reload data over your sqldatareader (at least I guess you mean set by using the word "refresh") by pressing a button you simply have to access the database again with the same code you are already using. But the important point here is, that you are using a bad design. Therefore I point out an article (30 mins to read) which helped me a lot to improve my code and therefore got rid of code duplication.
Please read: http://imar.spaanjaars.com/416/building-layered-web-applications-with-microsoft-aspnet-20-part-1
After you have read this article I will promise you that you will have a better understanding of how you have to access data in the database within your application

Related

Why does windows form freeze when it loads in C#?

I am new to C# and I am using windows forms.
I am building an application and I am facing a strange serious problem when Form loads.
I have 2 forms:
Form1 has a button_Edit and DataGridView
Form2 has a DataGridView1 and DataGridView2
As it is shown in the code and the screen shot, in Form1 when I select a row in DataGridView then click on Button_Edit the Order number and DateTime values in DataGridView on Form1 are passed to Form2 and then Form2 opens up.
Now in Form2 Load event there is a SQL query which takes Order number and DateTime to bring the relevant order details and then fill DataGridView1 and DataGridView2 in Form2.
In Form1:
Form2 frm2 = new Form2();
private void button_Edit_Click(object sender, EventArgs e)
{
frm2._ Order_Number= Convert.ToInt32(dataGridView1.SelectedRows[0].Cells[0].Value);
frm2._ Date_Time= Convert.ToDateTime(dataGridView1.SelectedRows[0].Cells[4].Value);
frm2.ShowDialog();
}
In Form2:
SqlConnection MyConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString);
SqlCommand MyCommand = new SqlCommand();
DataTable DataTable = new DataTable();
SqlDataAdapter Sql_Data_Adapter = new SqlDataAdapter();
int Order_Number;
DateTime Date_Time;
int i;
double Sum;
int RowIndex;
public int _ Order_Number
{
set { Order_Number = value; }
}
public DateTime _ Date_Time
{
set { Date_Time = value; }
}
private void Form2_Load(object sender, EventArgs e)
{
DataTable.Rows.Clear();
DataTable.Columns.Clear();
MyConnection.Open();
MyCommand.CommandText = "SELECT * FROM Customer_Order_Details WHERE Order_Number = #OrderNumber and Date_Time = #DateTime ";
MyCommand.Connection = MyConnection;
MyCommand.Parameters.Add("#OrderNumber", SqlDbType.Int).Value = Order_Number;
MyCommand.Parameters.Add("#DateTime", SqlDbType.DateTime).Value = Date_Time;
Sql_Data_Adapter.SelectCommand = MyCommand;
Sql_Data_Adapter.Fill(DataTable);
MyCommand.Parameters.Clear();
MyConnection.Close();
dataGridView1.Rows.Clear();
dataGridView2.Rows[0].Cells[1].Value = 0;
Sum = 0;
//////////////FILL THE ORDER INTO DATAGRIDVIEW1///////////
RowIndex = DataTable.Rows.Count - 1;
for (i = 0; i <= RowIndex; i++)
{
dataGridView1.Rows.Add(DataTable.Rows[i][2], DataTable.Rows[i][3], DataTable.Rows[i][4]);
// Calculate the total:
Sum = Convert.ToDouble(DataTable.Rows[i][4]) + Sum;
}
dataGridView2.Rows[0].Cells[1].Value = sum;
}
The issue:
This code works fine and as I wanted and DataGridView1 & DataGridView2 in Form2 are filled with the right details and it works fine when Form2 loads.
However, sometimes Form2 freezes after filling both DataGridView1 & DataGridView2 when Form2 loads and I can not do anything until I kill the Application using Task manager.
This issue happens sometimes and it is unpredictable. I really don’t know what is wrong.
I had a look here , here and here but non of those questions related to my issue. Note that I already use try catch and it does not throw anything because the form freezes. This freeze behavior occurs in the release mode I mean after I build EXE file then I install it in a PC and here the issue happens.
Has anyone got any idea why this bad unpredictable behavior occurs?
Is there anything that I should change in my code?
I will be very happy to listen to any new ideas/solutions no matter how small it is, it will be very beneficial.
Thank you
Do SQL work on another thread. Check out Asynchronous call.
BeginInvoke
I suggest using Async versions of Open (connecting to RDBMS) and ExecuteReader (query executing):
con.Open() -> await con.OpenAsync()
q.ExecuteReader() -> await q.ExecuteReaderAsync()
this easy substitution makes UI responsible (it doesn't freeze) while connecting to RDBMS and executing the query.
// do not forget to mark Form2_Load method as async
private async void Form2_Load(object sender, EventArgs e) {
// Do not share the connection - create it and dispose for each call
using (SqlConnection con = new SqlConnection(...)) {
await con.OpenAsync();
string sql =
#"SELECT *
FROM Customer_Order_Details
WHERE Order_Number = #OrderNumber
AND Date_Time = #DateTime";
// do not share command/query as well
using (SqlCommand q = new SqlCommand(sql, con)) {
q.Parameters.Add("#OrderNumber", SqlDbType.Int).Value = Order_Number;
q.Parameters.Add("#DateTime", SqlDbType.DateTime).Value = Date_Time;
dataGridView1.Rows.Clear();
dataGridView2.Rows[0].Cells[1].Value = 0;
Sum = 0;
// We actually don't want any sql adapter:
// all we have to do is to fetach data from cursor and append it to grids
using (var reader = await q.ExecuteReaderAsync()) {
while (reader.Read()) {
dataGridView1.Rows.Add(reader[2], reader[3], reader[4]);
Sum += Convert.ToDouble(reader[4]);
}
}
}
}
}
as said the code snippet you gave us isn't well written. You should use more Try/Catch Statements to prevent crashs and freezes on your programm. This will help you to find bugs even while running the Programm in release. Furthermore you have many options to solve your problem.
1:
Try to start Form2 in a second thread, then only your form2 will freeze until your sql finishes
2:
As mentioned before try to use asyncronous calls to avoid freeze time of handling the sql
3:
There is no direct need of a SQL Database/Connection. You could also use a Collection and create objects defined of your Products (like cola) and them bind them through the database. (If you are interested in i could show you a example)
The best way for you would be:
Add some Try/Catch Statements and get familiar with it, get familiar with Systems.Thread and try to start your form2 in a new thread if this doenst work go to step 2 and add asynchronus calls
In the end i would like to tell you, that namen your Forms "Form1" and "Form2" isn't nice could maybe you like to change it.

whats the use of data adapter

Can anyone explain why an SqlDataAdapter is used in the following code? The code is working fine without this adapter.
Also, why do we use DataAdapter? Please help me to understand this DataAdapter usage.
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
private void button1_Click(object sender, EventArgs e)
{
try
{
SqlConnection con = new SqlConnection("Data Source=.....\\SQLEXPRESS;Initial Catalog=......;Integrated Security=True");
con.Open();
SqlDataAdapter da =new SqlDataAdapter(); // Why use `SqlDataAdapter` here?
SqlCommand sc = new SqlCommand("insert into bhargavc values(" + textBox1.Text + "," + textBox2.Text + ");", con);
var o = sc.ExecuteNonQuery();
MessageBox.Show(o + "record to be inserted");
con.Close();
}
catch (Exception)
{
MessageBox.Show("error in the code");
}
}
private void button2_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
Data adapter works like a mediator between the database and the dataset. However, a data adapter cant store data. It just gives data from the database to the dataset.
For Example:
A water pipe is used to bring water from a source (well, pond, etc.) to a destination. However, the pipe isn't used to store water. In the same way, a data adapter (like a water pipe) sends data from the database to a dataset.
This should give a clearer understanding about data adapters.
A data adapter is used to read data from a data reader into a DataTable or a DataSet.
As you are not reading any data from the database in this code, the data adapter is completely superflous.
As a side note, you should use parameters instead of putting values directly into the query. Your code is totally open to SQL injection attacks.
There are several reasons to use a DataAdapter:
You can't fill a DataSet without one.
When the adapter completes its .Fill() method, it will close the connection for you; you don't have to explicitly call the .Close() method on your connection object. Although, it is still good practice to.
In your case, it isn't necessary to have one though. But, if you did want to use one, the implementation would look like this:
SqlDataAdapter da = new SqlDataAdapter();
DataSet ds = new DataSet();
da.Fill(ds);
From there, there are further actions that you can take on the ds object like exporting to Excel via Interop, filling a DataGridView or even updating a database table.
To fill either dataset or datatable
You don't have to close your SQL connection explicitly like .Close()

Provide a global access to database handler

I'm developing an application in C# (but this is not relevant, since i don't want to use any language facility) and I need to handle the connection to a database. I would avoid to explicitly create the connection in each method, like:
private void btnAnteprima_Click(object sender, EventArgs e)
{
SqlConnection myConnection = new SqlConnection("user id=***;" +
"password=***;server=***;" +
"database=***");
myConnection.Open();
SqlDataReader myReader = null;
SqlCommand myCommand = new SqlCommand("select * from *** where IDCliente=*", myConnection);
myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
MessageBox.Show(myReader["xyz"].ToString());
}
}
I would something like:
private void btnAnteprima_Click(object sender, EventArgs e)
{
SqlReader myReader = DbFactory.ExecuteQuery("select * from *** where IDCliente=*");
while (myReader.Read())
{
MessageBox.Show(myReader["xyz"].ToString());
}
}
As far as I know, the use of singleton pattern is useless or even harmfull in terms of performance. I wander about factory pattern to achieve this but i can't figure out how to do at its best. Did you have examples, paper to do this? I don't want reinvent the wheel, I just want use the right design pattern, and understand what's behind the wheel.
Take a look at the Data Access Block with the Microsoft Enterprise Library.
http://msdn.microsoft.com/en-us/library/ff664408(v=pandp.50).aspx

Use SqlDataAdapter to fill a table in a dataset with a new name, code don't run completely and no error

As you see, my code (it's in myform_load), when I run project, it continues to line 1. Just not run other lines after that. I got no error, but the code doesn't run completely. After it come to line one, myform is shown. Where is the problem?
SqlDataAdapter userSharj_history;
private void myform_Load(object sender, EventArgs e)
{
using (SqlConnection con = new SqlConnection(connectionString))
{
con.Open();
using (userSharj_history = new SqlDataAdapter(String.Format("SELECT * FROM users_sharj WHERE user_id = {0} AND datetime BETWEEN '{1}%' AND '{2}%'", user_id, az_tarikh_globalizationDateTimePicker1.Text, ta_tarikh_globalizationDateTimePicker1.Text), con))
{
1. userSharj_history.Fill(nan_DataSet, "sharjes");
2. gridControl1.DataSource = nan_DataSet.Tables["sharjes"];
}
con.Close();
}
view_btn.Focus();
}
The Query string is fine. I tested it in GUI Query Builder.
I use this dataset in my main form that call this form and there is no table in it with the name sharjes.
Either check the Output window or enable reporting of all exceptions. Visual Studio will not inform you about many exceptions by default.
Go to menu Debug --> Exceptions... and then tick Thrown for Common language runtime Exceptions and click OK. Run your code again and see if it throws an exception now.

DBConcurrencyException in SQL Database

He everybody,
Recently I've started a project that needs a lot of data. So much in fact it cannot be stored in the runtime memory.
I've been looking for solutions to this problem and have chosen for the use of a SQL databases.
I found a tutorial explaining how they work and recreated it myself. It makes sure your physical database and virtual dataset stay in sync by using a dataAdapter to update the database;
(FYI the tutorial can be found here: http://www.homeandlearn.co.uk/csharp/csharp_s12p1.html);
However when expanding a tutorial i came across an error i cant explain namely: DBConcurrencyException.
When i run the program all functionality works, i can add a row and delete a row. But when i try to do both in the same execution (order = add then delete) the error comes up.
It describes that zero of the one expected records were affected by the DeleteCommand.
The following code snippits is what i used:
Initialization:
private void Form1_Load(object sender, EventArgs e)
{
con = new SqlConnection();
ds1 = new DataSet();
con.ConnectionString = "Data Source=.\\SQLEXPRESS;AttachDbFilename=C:\\<Private>\\MyWorkers.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True";
con.Open();
string sql = "SELECT * From tblWorkers";
da = new SqlDataAdapter(sql, con);
da.Fill(ds1, "Workers");
NavigateRecords();
MaxRows = ds1.Tables["Workers"].Rows.Count;
updateIndicator();
con.Close();
//con.Dispose();
}
(Note: I commented out the directory for privacy reasons);
The addition of a row is done as followed:
private void btnSave_Click(object sender, EventArgs e)
{
SqlCommandBuilder cb = new SqlCommandBuilder(da);
DataRow dRow = ds1.Tables["Workers"].NewRow();
dRow[1] = textBox1.Text;
dRow[2] = textBox2.Text;
dRow[3] = textBox3.Text;
ds1.Tables["Workers"].Rows.Add(dRow);
MaxRows = MaxRows + 1;
inc = MaxRows - 1;
da.Update(ds1, "Workers");
MessageBox.Show("Entry Added");
}
When deleting a row this code is executed:
private void btnDelete_Click(object sender, EventArgs e)
{
SqlCommandBuilder cb = new SqlCommandBuilder(da);
ds1.Tables["Workers"].Rows[inc].Delete();
MaxRows--;
inc = 0;
NavigateRecords();
da.Update(ds1, "Workers");
MessageBox.Show("Record Deleted");
}
The NavigateRecord() method and setIndicator() method are not relevant in this question since they are GUI elements.
Thanks in advance everybody!
I came across this question statement while looking for a way to prevent SQL Server from locking an entire record (I want it to lock by field / column value instead) and noticed that no answer had been given, so here ya go if anyone else runs into this problem:
OP didn't actually ask a question, only stated what the problem was; so here's the answer to the question that wasn't asked "How do I prevent Database Concurrency Violations?":
Database Concurrency Violations (in this case) are preventable by making a decision as to which data gets to go in to the database. Most people elect to take the approach that 'last in wins'. So, in your handling of operations using the TableAdapter, put the Update in a Try/Catch and during Catch for DBConcurrencyException just make sure you do a quick Fill, then change whatever you were supposed to be changing, and then do the Update. Works every time.

Categories