I'm implementing an application on C# connected to a MySql database. Part of the application I'm showing data from MySql database table1 in a multi-line textbox in every 2 minutes, using a timer. Right now, the code is running perfectly. But, in the textbox1 which I'm using to show database table1 row values, It's just clearing the retrieved data and get whole bunch of data from the table and shows in the textbox view. The problem is when the database gets larger (like thousands of rows) it'll clear and retrieve all the row data over and over again in every 2 minutes.
private void timer1_Tick(object sender, EventArgs e)
{
string myConnection = "datasource=localhost;port=3306;username=root;password=";
MySqlConnection myConn = new MySqlConnection(myConnection);
MySqlCommand command = myConn.CreateCommand();
command.CommandText = "Select * FROM database_name.table1";
MySqlDataReader myReader;
try
{
myConn.Open();
myReader = command.ExecuteReader();
textBox1.Text = string.Empty; //Clearing the retrieved data
//looping and gets every row value from table1
while (myReader.Read())
{
if (textBox1.Text.Length > 0)
textBox1.Text += Environment.NewLine;
for (int i = 0; i < myReader.FieldCount; i++)
textBox1.Text += myReader[i].ToString() + " ";
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
myConn.Close();
}
There are two problems that I'm still struggling with:
01.) I want to get only the updated value from the data base.
02.) How to stick to the bottom in the multi-line text box when it keep updating?
Any help on this would be great.
Thanks in Advanced!
A posible solution for 01) is:
1) Store in a variable the last row id retrieved from table. (lastStoredID)
2) Change
command.CommandText = "Select * FROM database_name.table1";
to
command.CommandText = "Select * FROM database_name.table1 where id > " + lastStoredID ;
3) Remove line
textBox1.Text = string.Empty; //Clearing the retrieved data
Update:
If he wants only new inserted rows the solution above may be the right one.
If he wants not only just inserted rows, but updated rows the solution above is not the right one.
Related
In my current application I have a snippet of code that allows me to select a single row in a data grid view and store all the columns information into a variable to do with what I want. I use this primarily to send information from one SQL database table to another. It's great for only sending specified cells within a row.
Here is how I do a single row:
string ID = dataGridView1.SelectedRows[0].Cells[0].Value + string.Empty;
string itemOne= dataGridView1.SelectedRows[0].Cells[1].Value + string.Empty;
string itemTwo= dataGridView1.SelectedRows[0].Cells[2].Value + string.Empty;
string itemThree= dataGridView1.SelectedRows[0].Cells[3].Value + string.Empty;
var vItemOne = itemOne;
var vItemTwo= itemTwo;
var vItemThree= itemThree;
// ETC..
However, I now want to be able to select Multiple Rows and only insert specified columns within those rows to a SQL database.
I've tried modifying the above code to work... obviously it doesn't work.
I believe I need a loop, I haven't really used loops much so I'm not sure how to make it loop, skip certain columns, then insert into database.
This is what I am currently attempting, however I seem to be messing up somewhere.
using (SqlConnection con = new SqlConnection(Connection.MTRDataBaseConn))
{
for (int i = 0; i < dataGridView1.SelectedRows.Count; i++)
{
con.Open();
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "INSERT INTO dbo.[" + txtJobName.Text + "] ([Item One], [Item Two], [Item Three]) VALUES(#ItemOne,#ItemTwo,#ItemThree)";
cmd.Connection = con;
string strItemOne = this.dataGridView1.SelectedRows[i].Cells[1].Value + string.Empty;
string strItemTwo = this.dataGridView1.SelectedRows[i].Cells[2].Value + string.Empty;
string strItemThree = this.dataGridView1.SelectedRows[i].Cells[3].Value + string.Empty;
//Parameters
cmd.Parameters.AddWithValue("#ItemOne", strItemOne);
cmd.Parameters.AddWithValue("#ItemTwo", strItemTwo);
cmd.Parameters.AddWithValue("#ItemThree", strItemThree);
//execute
cmd.ExecuteNonQuery();
//close connection
con.Close();
}
}
...
While Debugging My dataGridView.SelectedRows.Count; i++ doesn't seem to be increasing and is staying at 0... I'm receiving the error when I try to return the selected row to a string. Shouldn't my selected rows still return a value?
I'm under the assumption my loop is wrong.
Can anyone help me with my issue?
Simply have to use a for each statement
string itemOne= dataGridView1.SelectedRows[0].Cells[1].Value + string.Empty;
string itemTwo= dataGridView1.SelectedRows[0].Cells[2].Value + string.Empty;
string itemThree= dataGridView1.SelectedRows[0].Cells[3].Value + string.Empty;
var vItemOne = itemOne;
var vItemTwo= itemTwo;
var vItemThree= itemThree;
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
//Insert Query Here
}
I am trying to save an online MySql database to a local Sqlite database. What I do is, try to get whole data from MySql to a datatable then from the datatable save it to the Sqlite. So, I tried to make sure that I get all the data from the MySql first counting the datatable through "Console.printLine".
The problem is, when I count the data in the PhpMyAdmin of the MySql, using SELECT COUNT(REFENCE) I get a count of 83,335 rows but in my Console.WriteLine, using the increment +1, I only get up to 3,857 rows which made me to believe that what I am getting is incomplete. Can you show me where I am wrong. If you have better way of copying then Online MySql "table" data to Sqlite table that would be great. Thank you.
private void buttonX1_Click(object sender, EventArgs e)
{
const string sql1 =
#"SELECT reference, DATE(trx_date) as 'date', chassis_nmbr, status, remarks,
approved_by, DATE(date_approved), branch_code FROM jobcomp_hdr;";
var table = new DataTable("onlineData");
using (var conn = new DwoAccess().ConnectToMySql())
{
using (var cmd = new MySqlCommand(sql1, conn))
{
try
{
cmd.CommandTimeout = 60;
var adapt = new MySqlDataAdapter(cmd);
conn.Open();
adapt.Fill(table);
}
catch (Exception ex)
{
//ignore
}
}
}
var x=0;
foreach (DataRow row in table.Rows)
{
Console.WriteLine(row["reference"].ToString());
x += 1;
}
Console.WriteLine(x.ToString());
}
I think the problem is with time of executing query and timeout, number of all rows is to big and executing it is to long. So You can use LIMIT where you set number rows to skip and number rows to get. Using for loop and quantity of all rows in table you will be able take tables divided into several parts 1,000 items in this case.
Here you find more about LIMIT in mysql ,samples
for (int i = 0; i <= rowsNumberInTable; i = i + 1000)
{
...
string sql1 =#"SELECT reference, DATE(trx_date) as 'date', chassis_nmbr, status, remarks, approved_by, DATE(date_approved), branch_code FROM jobcomp_hdr LIMIT " + i + #" ," + i+ 1000;
...
}
I have a comboBox and a checkListBox in my windows form application that connected to my SQL database. I got the binding data part working, but I am not sure how to show the datas in checkListBox when the comboBox item is selected. Let say I have 10 items in my comboBox that bind with my SQL database and they are under the column name ("application name ") such as excel, word, android, eclipse etc.... I call this method when the form begin to load. Sorry for the long code.
Here is my code for that applicationComboBox
private void loadComboBox()
{
myConn = new SqlConnection("Server = localhost; Initial Catalog= dbName; Trusted_Connection = True");
try
{
myConn.Open();
//my table name is Application_Detail
string query = "select * from Application_Detail";
myCommand = new SqlCommand(query, myConn);
//reading the value from the query
SqlDataReader dr = myCommand.ExecuteReader();
//Reading all the value one by one
while (dr.Read())
{
//column is 1 in Application_Detail Data
//GetString(1) display the 2nd column of the table
string name = dr.GetString(1);
//display the application name in column 2 -
applicationComboBox.Items.Add(name);
}
myConn.Close();
}catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
The outcome of this part of code is:
//label Name //Application Name
Application Name:
Excel
Word
NotePad
PowerPoint
SubLime
Eclipse
After I call this method, I want to display the teacher name that is according to what the user selected in this applicationComboBox. So if teacher 1,2,3 is using Excel and the user selected excel from the comboBox, the checkListBox will display teacher 1,2,3 and vice versa. To do this, I call the method at the comboBox1_SelectedIndexChanged method because I want to display the detail when I select an item from the comboBox. Below is my code
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
//I check if the comboBox index is at 0, it disable the button.
if (applicationComboBox.SelectedIndex == 0)
{
exportButton.Enabled = false;
this.teacherCheckListBox.DataSource = null;
teacherCheckListBox.Items.Clear();
}
//it it is not at 0,
else
{
exportButton.Enabled = true;
//call this method
fill_checkListBox();
}
//teacherCheckListBox
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void fill_checkListBox()
{
myConn = new SqlConnection("Server = localhost; Initial Catalog= dbName; Trusted_Connection = True");
try
{
myConn.Open();
//for reading purpose, I break down by long statement
//In this statement, I left join 3 table (Teacher_Detail, AppUser_Detail, and Application_Detail table). My AppUser_Detail contains all 3 id (teacherId, applicationId, and AppUserId). I then set filter the table using `where` keyWord to make the applicationId = the comboBox text
string query = "SELECT
td.chineseName,
ad.applicationId,
aud.applicationId,
ad.applicationName
FROM[AppUser_Detail] as aud
LEFT JOIN[Teacher_Detail] as td
ON aud.teacherId = td.teacherId
LEFT JOIN[Application_Detail] as ad
ON aud.applicationId = ad.applicationId
where aud.applicationId = '" + applicationComboBox.Text + "' AND NOT(td.teacherId IS NULL)
";
myCommand = new SqlCommand(query, myConn);
//reading the value from the query
SqlDataReader dr = myCommand.ExecuteReader();
//Reading all the value one by one
while (dr.Read())
{
//column is 0 where the teacherName belong in my Teacher_Detail table
string name = dr.GetString(0);
//I tried to set the text of the checkListBox as the teacherName, but I can't somehow
teacherCheckListBox.Text = name;
}
myConn.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
When I run the program like this, it said Conversion failed when converting the varchar value "Excel" to data type int. Is there a way to fix it? it shouldn't be a problem because in my Application_Detail table, my applicationName's and my teacherName's data type is set as nvarchar(50) and applicationId and teacherId = int;
The problem is with this line, I would think:
where aud.applicationId = '" + applicationComboBox.Text +
Based on your code, I would think that applicationId is an int and applicationComboBox.Text is just that, text.
Try this:
where ad.applicationName = '" + applicationComboBox.Text.Trim() +
Try this:
if (string.IsNullOrWhiteSpace(teacherCheckListBox.FindString(name))
{
teacherCheckListBox.Items.Add(name);
}
I have done this before, but for the life of me I can't remember how this worked.
I have a database that has a bunch of rows with data in them like names and ID numbers. What I need to do is populate a treeview from names in the database. I am running up against an issue just getting the reader to read multiple rows in the database. It only seems to be reading the first row and not subsequent rows. the actual task would be similar to below :
For each row in database add a parent node to treeview where the name is = to (reader[4].ToString()). That's about it. At the moment all I am trying to do is just get it to pop a messagebox showing that it's reading the multiple rows.
Please what am I missing to get this working?
SqlCeConnection conn = null;
try
{
using (conn = new SqlCeConnection("Data Source =" + ConfigurationFile + "; Password =*********"))
{
conn.Open();
SqlCeCommand cmd = conn.CreateCommand();
cmd.CommandText = "select * from t_mainprofiles";
cmd.ExecuteNonQuery();
var reader = cmd.ExecuteReader();
while (reader.Read())
{
ID = (Convert.ToInt32(reader[1]));
profileID = (Convert.ToInt32(reader[2]));
profileNAME = (reader[4].ToString().Trim());
profileLOC = (reader[5].ToString().Trim());
profileCHILD = (reader[6].ToString().Trim());
}
MessageBox.Show(profileNAME);
reader.Close();
}
}
catch(Exception error)
{
MessageBox.Show(""+error);
System.Diagnostics.Process.GetCurrentProcess().Kill();
}
finally
{
conn.Close();
}
Try removing the line cmd.ExecuteNonQuery();
Here is an example from MSDN
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.read(v=vs.110).aspx
I'm creating an application in Visual Studio 2010 C# and MySQL where the user can add, edit, view an employee. I already done with adding and viewing part. However I'm little confused in editing. I have this listView in my form where it displays all the employee added to the database. What I want is that whenever the user will select an employee and click edit button I want the values saved in the database to show in the corresponding textboxes below the listView. Can someone give me any idea how to do this? Please
Screenshot:
Code for listView:
private void getEmployee()
{
listViewEmployee.Items.Clear();
string cmd = "select employee_number, employee_lastname, employee_firstname, employee_middlename, employee_position, employee_datehired from employee";
DBConn db = new DBConn();
DataTable tbl = db.retrieveRecord(cmd);
foreach (DataRow row in tbl.Rows)
{
ListViewItem lv = new ListViewItem(row[0].ToString());
lv.SubItems.Add(row[1].ToString() + ", " + row[2].ToString() + " " + row[3].ToString());
lv.SubItems.Add(row[4].ToString());
lv.SubItems.Add(row[5].ToString());
listViewEmployee.Items.Add(lv);
}
}
private void textBoxSearchEmployee_TextChanged(object sender, EventArgs e)
{
string cmd = "SELECT employee_number, employee_lastname, employee_firstname, employee_middlename, employee_position, employee_datehired FROM employee where employee_lastname Like '" + textBoxSearchEmployee.Text + "%'";
listViewEmployee.Items.Clear();
DBConn db = new DBConn();
DataTable tbl = db.retrieveRecord(cmd);
foreach (DataRow row in tbl.Rows)
{
ListViewItem lv = new ListViewItem(row[0].ToString());
lv.SubItems.Add(row[1].ToString() + ", " + row[2].ToString() + " " + row[3].ToString());
lv.SubItems.Add(row[4].ToString());
lv.SubItems.Add(row[5].ToString());
listViewEmployee.Items.Add(lv);
}
}
It seems to me you are able to populate the listView only.
A few pointers:
1) The way you're writing your SQL statement now is prone to SQL Injection. Use parameters in your SQL commands instead of directly concatenating the variables to your query. See this question for an example on how to do it.
2) Depending on where your other relevant data is located (i.e. if your database is normalized), you might have to do a join in your query.
string sqlQuery = "SELECT * FROM employee
JOIN other_employee_data_table on other_employee_data_table.employeeID = employee.ID
WHERE employee.employee_lastname LIKE #employee_lastname +'%'"
But if your employee table contains all the data, then no need to do a join. Just get all the relevant information from that table.
3) Once you got all the information you need, it's just a matter of reading those data and assigning them to their respective fields.
Pseudo Code:
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
connection.Open();
MySqlCommand command = connection.CreateCommand();
command.CommandText = sqlQuery;
command.CommandType = System.Data.CommandType.Text;
// add parameters in this line
using (MySqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
// iterate in each row
for (int i = 0; i < reader.FieldCount; i++)
{
// iterate each column using reader.GetValue(i)
}
}
}
}
When the user presses the "edit" button...
Retrieve the selected employee
Use a SELECT to get the selected employee's information
Populate the text boxes with the selected employee's information
For example,
String employee = listViewEmployee.Text;
String cmd = "SELECT * FROM employee WHERE employee_lastname='" + employee + "'";
DBConn db = new DBConn();
DataTable tbl = db.retrieveRecord(cmd);
txtLastName.Text = tbl.Rows[0][0];
// ...
// etc.
Note: It's a bad idea to concatenate values into a SQL query because if the values are malicious, a different query could be executed. For example, if employee had the value of x' OR '1'='1; DROP TABLE employee; -- or something along those lines, then the employee table could be dropped. The way around this is using Stored Procedures or parameterized queries.