I am developing windows form application, I have carefully written the program and it is working absolutely fine on the Touch Screen POS system with 2 GB Ram and SSD (Windows 10).
I am facing a very strange issue when using it on a relatively fast computer (16Gb RAM, i7 10th gen). Let me be a little descriptive about it.
Basically, I have designed an application to handle restaurant billing, which has a simple flow as below
- Add Items to Cart -> 2) Place Order -> 3) Pay for Order -> 4) Print Receipt.
The issue is on the 3rd step when I make payment, it takes 1 second to insert (update) into the database and the same for reading it again to be printed on the receipt. on a fast computer, it is being processed as data has not yet been inserted.
I have two forms executing separate functions
- POS form - this will handle cart items and save invoice details into the database (without payment info) after saving the invoice it will popup Pay Form as Dialog and will wait for Dialog Result to print a receipt.
CODE ON POS FORM
//AFTER INSERTING ALL ITEMS AND INVOICE INTO DATABASE
Pay p = new Pay(label_order_no.Text);
if (p.ShowDialog() == DialogResult.OK)
{
try
{
//dt_cart is DataTable containing cart items - already inserted into database.
if (dt_cart.Rows.Count > 0)
{
if (MessageBox.Show("DO YOU WANT TO PRINT BILL?", "CONFIRM BILL PRINT", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
//tw.getData is just simplified method(for this question) with select MS ACCESS sql statement which will return value from column "BALANCE" of selected order from database.
// BALANCE - COLUMN NAME IN DB, INVOICES - TABLE NAME IN DB, ORDER_ID IS PRIMARY KEY
if (tw.getData("BALANCE", "INVOICES", "WHERE ORDER_ID = " + label_order_no.Text) != "")
{
print_bill(); // THIS WILL PRINT BILL, BUT AMOUNTS WILL NOT BE DISPLAYED ON BILL AS IT IS TAKING TIME TO GET UPDATED
}
else
{
Thread.Sleep(3000); // IF THREAD IS PAUSED FOR 2 OR 3 SECONDS BILL IS GETTING PRINTED PROPERLY. IT IS NOT POSSIBLE TO STOP FOR 3 SECONDS AS RETAIL COUNTERS ARE VERY CROWDED AND WORKERS ARE OPERATING BILLING VERY FAST WITH SHORTCUT KEYS.
print_bill();
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
- Pay Form - this will handle payment method, amount, due, etc, and will UPDATE into the existing database (Single ROW, only 4-5 columns will be updated). After updating the database this form will return the dialog result of OK to let the POS form know that database has been updated and printing receipt is a go.
CODE ON PAY FORM
//PAID AND COMPLETED ARE BOOLEAN VALUES SET AS FALSE BY DEFAULT
//IF CUSTOMER IS PAYING FULL AMOUNT THEN PAID AND COMPLETED WILL BE SET TO TRUE
if (paid == false)
{
//FOR PARTIAL PAYMENT OR CREDIT SALE
if (MessageBox.Show("PAYMENT INCOMPLETE, ARE YOU SURE TO PROCEED?", "CONFIRM", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
//tw.insertData will execute non query (insert or update) and will return "SUCCESS" as string or error message
string updateInvoice = tw.insertData("UPDATE INVOICES SET CASH_PAID = " + total_cash_paid.ToString() + ", CARD_PAID = " + tb_card_partial.Text + ", UPI_PAID = " + tb_upi_partial.Text + ", BALANCE = " + tb_due.Text + ", PAID = " + paid + ", COMPLETED = " + completed + " WHERE ORDER_ID = " + label_order_id.Text);
if (updateInvoice == "SUCCESS")
{
MessageBox.Show("PAYMENT SUCCESSFUL!", "SUCCESS", MessageBoxButtons.OK, MessageBoxIcon.Information);
this.DialogResult = DialogResult.OK;
//AFTER UPDATE SUCCESSFUL FORM WILL RETURN DIALOG RESULT OK TO POS FORM FOR PRINTING RECIEPT
}
else
{
MessageBox.Show("ERROR - " + updateInvoice, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
else
{
//FOR COMPLETED PAYMENT PAID AND COMPLETED WILL BE SET TO TRUE
//tw.insertData will execute non query (insert or update) and will return "SUCCESS" as string or error message
string updateInvoice = tw.insertData("UPDATE INVOICES SET CASH_PAID = " + total_cash_paid.ToString() + ", CARD_PAID = " + tb_card_partial.Text + ", UPI_PAID = " + tb_upi_partial.Text + ", BALANCE = " + tb_due.Text + ", PAID = " + paid + ", COMPLETED = " + completed + " WHERE ORDER_ID = " + label_order_id.Text);
if (updateInvoice == "SUCCESS")
{
MessageBox.Show("PAYMENT SUCCESSFUL!", "SUCCESS", MessageBoxButtons.OK, MessageBoxIcon.Information);
this.DialogResult = DialogResult.OK;
//AFTER UPDATE SUCCESSFUL FORM WILL RETURN DIALOG RESULT OK TO POS FORM FOR PRINTING RECIEPT
}
else
{
MessageBox.Show("ERROR - " + updateInvoice, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
By analyzing the above codes you can clearly see that I am not calling the print_bill() method unless the Pay form is returning "OK" as a dialog result. only after updating data in the database.
The receipt looks like below, the left one is printed instantly, the right one is printed with a 3-sec pause.
The computer with lower ram and speed takes its time to load UI, hence it is working properly there, but on faster computers, I am facing this issue, how can it be solved? Thanks in advance!
Notes:
- I have simplified insert and update and select methods for this question only, I am calling proper OleDbCommand with monitored DB connections, and catching exceptions.
- It will also help to know more about optimizing MS ACCESS DB insert/update speed.
- Attached DB Table for reference See Image SEE INVOICES TABLE
UPDATE
tw.insertData(string query);
is a method with following code
public string insertData(string query)
{
if (connection_mode == "access")
{
try
{
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
OleDbCommand cmd = new OleDbCommand(query, conn);
cmd.ExecuteNonQuery();
cmd.Dispose();
return "SUCCESS";
}
catch (Exception ex)
{
return ex.Message;
}
finally
{
if (conn.State == ConnectionState.Open)
{
conn.Close();
}
}
}
else
{
try
{
if (con.State == ConnectionState.Closed)
{
con.Open();
}
SqlCommand cmd = new SqlCommand(query, con);
cmd.ExecuteNonQuery();
cmd.Dispose();
return "SUCCESS";
}
catch (Exception ex)
{
return ex.Message;
}
finally
{
if (conn.State == ConnectionState.Open)
{
conn.Close();
}
}
}
}