When I can't reach Mysql server ip, winform GUI freezes - c#

I am working on a project about data acquisition. I get data via RasPi3b+ from machines. Data is held Mysql on Raspi server. To track data, I have made a dashborad by using C# winforms. Sometimes machines are shut down and I can't reach Mysql server. When that happens winforms freezes. I don't want it to freeze (maybe a green indicator turns red but it should not affect GUI ). How can I fix this ?
This is my timer code that is triggered every 2 second.
private void timer1_Tick(object sender, EventArgs e)
{
for (int i = 0; i < (IpAndNames.Count ); i++)
{
string today = DateTime.Now.ToString("yyyy-MM-dd");
_lblListOpen[i].Text = "open: " + _machineDal.SpenTime(today, IpAndNames[i].Ip, "Logs", "Machine","open").ToString();
_lblListClose[i].Text = "close: " + _machineDal.SpendTime(today, IpAndNames[i].Ip, "Logs", "Machine","close").ToString();
string lastState = _machineDal.LastDateAndState(IpAndNames[i].Ip, "Machine", "Logs").LastState;
DateTime lastTime = _machineDal.LastDateAndState(IpAndNames[i].Ip, "Machine", "Logs").LastDate;
TimeSpan spendTime= DateTime.Now - lastTime;
_lblListWorkingTime[i].Text = lastState +" "+ spendTime.ToString("h'h 'm'm 's's'");
}
}
This is my data layer code
public TimeSpan SpendTime(string date, string ip, string tableName, string db, string state)
{
TimeSpan openTime= new TimeSpan(0, 0, 0);
string connString = "server=" + ip + ";user=root;database=" + db + ";port=3306;password=root;Connection Timeout=1";
try
{
using (_conn = new MySqlConnection(connString))
{
string query = "SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(time ) ) ) AS timeSum FROM " + tableName + " " +
"WHERE Laststate='" + state + "' " +
"and date like \"" + date + "%\"";
using (MySqlCommand cmd = new MySqlCommand(query, _conn))
{
_conn.Open();
using (MySqlDataReader reader = cmd.ExecuteReader())
{
reader.Read();
if (!reader.IsDBNull(0))
{
openTime= reader.GetTimeSpan(0);
}
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
return openTime;
}

Related

Visual Studio Database Not Updating

I am working on a school project and for some reason my mysql database doesn't update despite no of row changed is more than 0 and triggering the Update sucessful alert. It also manage to only update my image data from my fileupload.
**admin_products_details_edit.aspx.cs**
protected void btn_ProdEdit_Click(object sender, EventArgs e)
{
int result = 0;
string image = "";
if (FileUpload_ProdImg.HasFile == true)
{
image = "images\\" + FileUpload_ProdImg.FileName;
img_result.ImageUrl = FileUpload_ProdImg.FileName;
}
else
{
image = img_result.ImageUrl;
}
Product Prod = new Product();
string datProdID = lbl_ProdID.Text;
string datProdName = tb_ProdName.Text;
string datProdDesc = tb_ProdDesc.Text;
string datProdImg = img_result.ImageUrl;
decimal datProdPrice = decimal.Parse(tb_ProdPrice.Text);
int datProdCal = int.Parse(tb_ProdCal.Text);
int datStockLvl = int.Parse(tb_StockLvl.Text);
result = Prod.ProductUpdate(datProdID, datProdName, datProdDesc, datProdImg, datProdPrice, datProdCal, datStockLvl);
if (result > 0)
{
string saveimg = Server.MapPath(" ") + "\\" + image;
FileUpload_ProdImg.SaveAs(saveimg);
Response.Write("<script>alert('Update successful');</script>");
Response.Redirect("admin_products_details.aspx?ProdID=" + datProdID);
}
else
{
Response.Write("<script>alert('Update fail');</script>");
}
}<-The code for the button edit event trigger
**Product.cs**
...public int ProductUpdate(string upID, string upName, string upDesc, string upImg, decimal upPrice, int upCal, int upstkLvl)
{
string queryStr = "UPDATE Products SET" + " ProdName = #productName, " + " ProdDesc = #productDesc, " + " ProdImg = #productImage, " + " ProdPrice = #productPrice, " + " ProdCalorie = #productCal, " + " StockLevel = #productStkLvl " + " WHERE ProdID = #productID";
SqlConnection conn = new SqlConnection(_connStr);
SqlCommand cmd = new SqlCommand(queryStr, conn);
cmd.Parameters.AddWithValue("#productID", upID);
cmd.Parameters.AddWithValue("#productName", upName);
cmd.Parameters.AddWithValue("#productDesc", upDesc);
cmd.Parameters.AddWithValue("#productImage", upImg);
cmd.Parameters.AddWithValue("#productPrice", upPrice);
cmd.Parameters.AddWithValue("#productCal", upCal);
cmd.Parameters.AddWithValue("#productStkLvl", upstkLvl);
conn.Open();
int nofRow = 0;
nofRow = cmd.ExecuteNonQuery();
conn.Close();
return nofRow;
}<-The code for updating the mysql database,located in a different cs file,titled Product.cs
My mysql database table is called Products
Thank you very much for your help in advance.

assistance with optimization

not sure if stackoverflow is normally used for stuff like this but i'm looking for assistance in optimizing my code. I am running a method to query a count from a database which is fast and works fine. and a timer that is set to run this every 5 minutes. When i implement the timer in my main window after initialization it freezes when opening the window for 30+ seconds. It didn't do that before I added the timers. Any help optimizing this or tips on improving the way this works would be great!
Method that runs SQL query:
public string SQLDataTotalCalls()
{
DateTime dte = DateTime.Today;
string fixedStartDate = String.Format("{0:yyyy-MM-dd " + "05:00:00.000" + "}", dte);
string fixedEndDate = String.Format("{0:yyyy-MM-dd " + "05:00:00.000" + "}", dte.AddDays(1));
SqlConnection connection = null;
using (connection)
{
try
{
var dataSet = new DataSet();
connection = new SqlConnection("Data Source=QL1OADB1;Initial Catalog=OADB;User Id=;Password=");
connection.Open();
var command = new SqlCommand("SELECT COUNT(SOURCEID) AS 'MYCOUNT' "
+ "FROM [OADB].[oadb].[CmsCallHistory] "
+ "WHERE disposition = 2 and DISPSPLIT in (" + SkillNumber + ") AND SEGSTOP BETWEEN '" + fixedStartDate + "' and '" + fixedEndDate + "'",
connection)
{
CommandType = CommandType.Text
};
var dataAdapter = new SqlDataAdapter { SelectCommand = command };
dataAdapter.Fill(dataSet);
return dataSet.Tables[0].Rows[0]["MYCOUNT"].ToString();
}
catch (Exception e)
{
throw new Exception(e.Message, e);
}
finally
{
if (connection != null)
{
connection.Close();
}
}
}
}
Timer that triggers the method every 5 minutes:
public async Task RunPeriodicQueryTotalCalls()
{
TimeSpan interval = TimeSpan.FromMinutes(5);
while (true)
{
await Task.Delay(interval);
string result = await Task.Run((Func<string>)SQLDataTotalCalls);
TotalDailyCalls = result;
}
}
This is where i initialize the window. please note that I run these querys also when the application first launches before the timer runs otherwise the numbers will not post until it runs 5 minutes later:
public ScoreBoardBigViewWindow()
{
InitializeComponent();
string value = "Enter Skill Number Here";
if (Tmp.InputBox("New document", "New document name:", ref value) == System.Windows.Forms.DialogResult.OK)
{
SkillNumber = value;
}
TotalDailyLast7Days = SQLDataSevenPastCalls();
TotalDailyCalls = SQLDataTotalCalls();
TotalDailyAbandon = SQLDataAbandonCalls();
RunPeriodicQueryTotalCalls();
RunPeriodicQueryAbandonCalls();
}
If i remove RunPeriodicQueryTotalCalls(); and RunPeriodicQueryAbandonCalls(); then the performance issue goes away.
If stackoverflow is not the right place to ask this type of question please let me know and I'll reach out to other avenues for further assistance.

C# Clear Biometric logs after logging into postgresql database without any loss of data

I have developed a windows service which will log all the bio-metric logs. For this to run, i have used npgsql for postgres connectivity. The below code will do all the work and to activate the logging , i have used the timer in the windows service which will run the below function for every 1 hour. The below code works fine for collecting the attendance log from the bio-metric. But, What i need is, after the collecting the log and writing it to the database table, it should clear the logs in the bio-metric device. Please consider the below scenario before doing that.
1.at 1:00 windows service starts collecting data.
2.at 1:10 service finish collecting data.
3.at 1:10, service needs to clear the log.
4.While clearing the log, if any person access the device, that log should not be omitted.
OpenConn() & CloseConn() are used to open and close the database connection.
Flush() is used to clear the memory.
public void getLog()
{
bIsConnected = axCZKEM1.Connect_Net("xxx.xxx.xxx.xxx", Convert.ToInt32("4370"));
if (bIsConnected == true)
{
LogEntry(string.Format("{0} : Biometric Device Connected", DateTime.Now));
string sdwEnrollNumber = "";
int idwVerifyMode = 0;
int idwInOutMode = 0;
int idwYear = 0;
int idwMonth = 0;
int idwDay = 0;
int idwHour = 0;
int idwMinute = 0;
int idwSecond = 0;
int idwWorkcode = 0;
int idwErrorCode = 0;
int iGLCount = 0;
// int iIndex = 0;
if (this.axCZKEM1.ReadGeneralLogData(iMachineNumber))//read all the attendance records to the memory
{
while (this.axCZKEM1.SSR_GetGeneralLogData(iMachineNumber, out sdwEnrollNumber, out idwVerifyMode,
out idwInOutMode, out idwYear, out idwMonth, out idwDay, out idwHour, out idwMinute, out idwSecond, ref idwWorkcode))//get records from the memory
{
var first = iGLCount.ToString();
var second = sdwEnrollNumber;//modify by Darcy on Nov.26 2009
var third = idwVerifyMode.ToString();
var fourth = idwInOutMode.ToString();
var fifth = idwYear.ToString() + "-" + idwMonth.ToString() + "-" + idwDay.ToString() + " " + idwHour.ToString() + ":" + idwMinute.ToString() + ":" + idwSecond.ToString();
var sixth = idwWorkcode.ToString();
string check1 = "False";
try
{
this.OpenConn();
//LogEntry(string.Format("{0} : Opens connection", DateTime.Now));
string SQL = "select exists(select bio_enrollno from bio_branch where bio_datetime = '" + fifth + "')";
using (NpgsqlCommand cmd1 = new NpgsqlCommand(SQL, conn))
{
NpgsqlDataReader dr = cmd1.ExecuteReader();
while (dr.Read())
{
for (int i = 0; i < dr.FieldCount; i++)
{
string output = dr[i].ToString();
if (output.Equals(check1))
{
this.CloseConn();
//LogEntry(string.Format("{0} : string equal and opens connection", DateTime.Now));
this.OpenConn();
string SQL1 = "INSERT INTO bio_branch(bio_enrollno, bio_verifymode, bio_inoutmode, bio_datetime, bio_workcode) VALUES ('" + second + "','" + third + "','" + fourth + "' ,'" + fifth + "', '" + sixth + "')";
NpgsqlCommand command1 = new NpgsqlCommand(SQL1, conn);
Int32 rowsaffected1 = command1.ExecuteNonQuery();
//LogEntry(string.Format("{0} : DB Write Successfull", DateTime.Now));
this.CloseConn();
}
}
}
//LogEntry(string.Format("{0} : Close Connection", DateTime.Now));
this.CloseConn();
}
}
catch (Exception err)
{
LogEntry(string.Format("{1} : Database Insert Error : {0}", err, DateTime.Now));
this.CloseConn();
break;
}
}
Flush();
}
else
{
axCZKEM1.GetLastError(ref idwErrorCode);
if (idwErrorCode != 0)
{
LogEntry(string.Format("{0} : Reading data from terminal failed,ErrorCode : {1}", DateTime.Now, idwErrorCode.ToString()));
}
else
{
LogEntry(string.Format("{0} : No data from terminal returns!", DateTime.Now));
}
}
axCZKEM1.Disconnect();
LogEntry(string.Format("{0} : Biometric Disconnected", DateTime.Now));
return;
}
else
{
LogEntry(string.Format("{0} : Please connect the device", DateTime.Now));
return;
}
}
After your SSR_GetGeneralLogData, you can add the following code
if (axCZKEM1.ClearGLog(iMachineNumber))
{
axCZKEM1.RefreshData(iMachineNumber);//the data in the device should be refreshed
LogEntry(string.Format("{0} : All att Logs have been cleared from teiminal!, Success", DateTime.Now));
}
else
{
axCZKEM1.GetLastError(ref idwErrorCode);
LogEntry(string.Format("{0} : Clear operation failed", DateTime.Now));
}
This will clear the log data in the device (do it after you saved the data) and the next download will be much faster because the machine allways will be with just a few logs.

c# if Scanner reading save to database -- form background--Motorola hand scanner

I wrote a simple program for reading with hand scanner code 39 barcode(USB port) to textbox and save the result ('if textbox changed') to database. But if the form is hidden then it is not read to the correct place. Can someone help me to solve this problem? I think somehow if the scanner reading then save automatically to database but how?
some code:
void countDown_Tick(object sender, EventArgs e)
{
TimeRemained--;
if (TimeRemained == 0 && (txt_kod.Text != ""))
{
try
{
if (txt_kod.Text.Length == 4 )
{
connection.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
//MessageBox.Show(mini);
command.CommandText = " insert into Jelenlet (Kod,Datum) values ('" + txt_kod.Text + "','" + adat + "')";
command.ExecuteNonQuery();
// MessageBox.Show(txt_kod.Text);
connection.Close();
txt_kod.Text = String.Empty;
}
else
{
//MessageBox.Show("Rossz beolvasás");
Console.Beep();
Console.Beep();
Console.Beep();
txt_kod.Text = String.Empty;
connection.Close();
}
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex);
connection.Close();
}
}
private void timer1_Tick(object sender, EventArgs e)
{
DateTime dateTime = DateTime.Now;
this.time_lbl.Text = dateTime.ToString("yyyy/MM/dd");
}
Timer countDown = new Timer();
int TimeRemained;
string adat;
private void textBox1_TextChanged(object sender, EventArgs e)
{
//timer2.Start();
countDown.Interval = 1000;
TimeRemained = 1;
countDown.Tick += new EventHandler(countDown_Tick);
countDown.Enabled = true;
// MessageBox.Show(idoszak_lbl.Text);
//MessageBox.Show(adat);
adat = time_lbl.Text + "." + idoszak_lbl.Text;
//adat = time_lbl.Text + "." + idoszak_lbl.Text + "." + lbl_hobbi.Text; // csütörtök vizsgálat esetén
}
I have lot of forms which is used in same time in this program and i wont wait for reading, i would like to automatize it.
I would like to use Motorola hand scanner.

Displaying a progressbar while executing an SQL Query

I want to inform the user while data is being read from an SQL database
and I decided to create a form with a progressbar but it doesn't work - maybe because a thread is needed. I want to create the form programmatically
ProgressBar pb = new ProgressBar();
pb.MarqueeAnimationSpeed = 30;
pb.Style = ProgressBarStyle.Marquee;
pb.Dock = DockStyle.Fill;
progressForm.ClientSize = new Size(200, 50);
progressForm.FormBorderStyle = FormBorderStyle.FixedDialog;
progressForm.StartPosition = FormStartPosition.CenterScreen;
progressForm.Controls.Add(pb);
progressForm.ControlBox = false;
progressForm.TopMost = true;
progressForm.Show();
//do data processes here (all queries and executes)
progressForm.close();
How do I modify the code above to achieve my stated goals?
edit: Btw, I want to use this progressbar form in every data functions in my project. For example: fillGrid, runQuery..
#Will thank you very much for your answers. I meant how can I use a function of class for example my gridFill function is in that connection class:
class ConnectionClass
{
public static SqlConnection connection = new SqlConnection();
public string sorgu;
public static string server;
public static string userId;
public static string catalog;
public static string password;
public static string accessMethod;
public DataSet ds = new DataSet();
Form progressForm = new Form();
public bool Open()
{
try
{
if (connection.State != ConnectionState.Open)
{
connection.ConnectionString = "Data Source = " + server + ";" +
"Initial Catalog=" + catalog + ";" +
"User ID=" + userId + ";" +
"Password=" + password + ";" +
"Connect Timeout=0";
connection.Open();
return true;
}
else
{
return true;
}
}
catch (Exception ex)
{
MessageBox.Show("System message:" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
public DataTable Dt(string query)
{
DataTable dt = new DataTable();
if (Open())
{
SqlDataAdapter da = new SqlDataAdapter(query, connection);
try
{
//progressForm.Showdialog() is this possible???
da.Fill(dt);
//progressForm.close(); ??
}
catch (Exception ex)
{
MessageBox.Show("Sistem Mesajı:" + ex.Message, "Hata", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
return dt;
}
public bool Run(string query, string hataMsj)
{
Form activeForm = Form.ActiveForm;
query = " SET DATEFORMAT DMY " + query;
SqlCommand sc = new SqlCommand(query, connection);
try
{
Open();
sc.ExecuteNonQuery();
return true;
}
catch (Exception )
{
return false;
}
}
public void fillComboBox(string sorgu, ComboBox cb, string text, string value)
{
DataTable dt = Dt(sorgu);
cb.DisplayMember = text;
cb.ValueMember = value;
cb.DataSource = dt;
if (cb.Items.Count > 0)
{
cb.SelectedIndex = 0;
}
}
public int fillGridView(string sorgu, DataGridView dgv)
{
DataTable dtGrvw = Dt(sorgu);
dgv.DataSource = dtGrvw;
return 1;
}
}
and example queries from another form(class)
ConnectionClass cc = new ConnectionClass();
query= " INSERT INTO tblPersonel (" +
" [sqlUserName] " +
",[personelNo] " +
",[ad] " +
",[soyad] " +
",[departmanId] " +
",[emailadres] " +
",[tcKimlikNo],[kangurubu],[dokumaciNo])VALUES" +
"('" + tbSqlUserName.Text +
"','" + tbPersonelNo.Text +
"','" + tbAd.Text +
"','" + tbSoyad.Text +
"','" + cbDepartman.SelectedValue.ToString() +
"','" + tbMail.Text +
"','" + tbKimlikno.Text +
"','" + tbKangrubu.Text +
"','" + tbDokumaciNo.Text + "' ) ";
if (cc.Run(query, "Unexpected error on insert new person"))
{
fillGrid();
this.Close();
}
public void fillGrid()
{
query= " select * from View_Personel order by personelNo desc";
cc.fillGridView(query, gridviewPersonel);
}
and I cant imagine how can I use it in bw_DoWork event. because my function has parameters.(query, gridview) when I call it from another class I can use it with parameters...
p.s. : this Method is pretty good for me but it didnt worked. I didnt understand the problem
Use the BackgroundWorker class to fill your DataGrid.
Form progressForm;
public void func() {
BackgroundWorker bw = new BackgroundWorker ();
bw.DoWork += new DoWorkEventHandler (bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler (bw_RunWorkerCompleted);
progressForm = new Form ();
ProgressBar pb = new ProgressBar ();
pb.MarqueeAnimationSpeed = 30;
pb.Style = ProgressBarStyle.Marquee;
pb.Dock = DockStyle.Fill;
progressForm.ClientSize = new Size (200, 50);
progressForm.FormBorderStyle = FormBorderStyle.FixedDialog;
progressForm.StartPosition = FormStartPosition.CenterScreen;
progressForm.Controls.Add (pb);
progressForm.ControlBox = false;
progressForm.TopMost = true;
progressForm.Show ();
string queryString = "SELECT ...."; // fill query string here
var params = new KeyValuePair<GridControl, string>(sorgu, queryString);
bw.RunWorkerAsync (params);
}
void bw_DoWork (object sender, DoWorkEventArgs e) {
KeyValuePair<GridControl, string> params = e.Argument as KeyValuePair<GridControl, string>;
ConnectionClass cc = new Connection Class();
cc.fillGrid(params.Value, params.Key);
}
void bw_RunWorkerCompleted (object sender, RunWorkerCompletedEventArgs e) {
progressForm.Close (); //
}
It is possible to send a parameter to the BackgroundWorker. If you need more than one parameter, you can send a Tuple which contains any objects you need.
EDIT: If you're on 3.5, you can use a KeyValuePair instead. Code is updated for that.
Just as Ash Burlaczenko recommended, you'll have to use a BackgroundWorker for that purpose.
Since, however, you'd like to tie it in with a ProgressBar, I'd recommend looking at this article on CodeProject: ProgressWorker.
It's fairly easy to use and it updates the progress bar for you automatically. All you'll have to do is remember to call the ProgressWorker.ReportProgress method from time to time in order to update the associated progress bar.

Categories