4.7.2. Loading the Invoice Data
The following method loads the invoice headers:
public void LoadInvoicesData() {
var dbContext = AppVariables.getDbContext();
var invoices =
from invoice in dbContext.INVOICES
where (invoice.INVOICE_DATE >= AppVariables.StartDate) &&
(invoice.INVOICE_DATE <= AppVariables.FinishDate)
orderby invoice.INVOICE_DATE descending
select new InvoiceView
{
Id = invoice.INVOICE_ID,
Cusomer_Id = invoice.CUSTOMER_ID,
Customer = invoice.CUSTOMER.NAME,
Date = invoice.INVOICE_DATE,
Amount = invoice.TOTAL_SALE,
Payed = (invoice.PAYED == 1) ? "Yes" : "No"
};
masterBinding.DataSource = invoices.ToBindingList();
}
To simplify type casting, we define an InvoiceView
class, rather than use some anonymous type. The definition is as follows:
public class InvoiceView {
public int Id { get; set; }
public int Cusomer_Id { get; set; }
public string Customer { get; set; }
public DateTime? Date { get; set; }
public decimal? Amount { get; set; }
public string Payed { get; set; }
public void Load(int Id) {
var dbContext = AppVariables.getDbContext();
var invoices =
from invoice in dbContext.INVOICES
where invoice.INVOICE_ID == Id
select new InvoiceView
{
Id = invoice.INVOICE_ID,
Cusomer_Id = invoice.CUSTOMER_ID,
Customer = invoice.CUSTOMER.NAME,
Date = invoice.INVOICE_DATE,
Amount = invoice.TOTAL_SALE,
Payed = (invoice.PAYED == 1) ? "Yes" : "No"
};
InvoiceView invoiceView = invoices.ToList().First();
this.Id = invoiceView.Id;
this.Cusomer_Id = invoiceView.Cusomer_Id;
this.Customer = invoiceView.Customer;
this.Date = invoiceView.Date;
this.Amount = invoiceView.Amount;
this.Payed = invoiceView.Payed;
}
}
The Load
method allows us to update one added or updated record in the grid quickly, instead of completely reloading all records. Here is the code of the event handler for clicking the Add button:
private void btnAddInvoice_Click(object sender, EventArgs e) {
var dbContext = AppVariables.getDbContext();
var invoice = dbContext.INVOICES.Create();
using (InvoiceEditorForm editor = new InvoiceEditorForm()) {
editor.Text = "Add invoice";
editor.Invoice = invoice;
// Form Close Handler
editor.FormClosing += delegate (object fSender, FormClosingEventArgs fe) {
if (editor.DialogResult == DialogResult.OK) {
try {
// get next sequence value
invoice.INVOICE_ID = dbContext.NextValueFor("GEN_INVOICE_ID");
// add a record
dbContext.INVOICES.Add(invoice);
// trying to save the changes
dbContext.SaveChanges();
// add the projection to the grid list
((InvoiceView)masterBinding.AddNew()).Load(invoice.INVOICE_ID);
}
catch (Exception ex) {
// display error
MessageBox.Show(ex.Message, "Error");
// Do not close the form to correct the error
fe.Cancel = true;
}
}
};
// show the modal form
editor.ShowDialog(this);
}
}
In our primary modules, the similarly-named method called dbContext.Refresh but, here, a record is updated by by calling the Load
method of the InvoiceView
class. The reason for the difference is that dbContext.Refresh
is used to update entity objects, not the objects that can be produced by complex LINQ queries.
The code of the event handler for clicking the Edit button:
private void btnEditInvoice_Click(object sender, EventArgs e) {
var dbContext = AppVariables.getDbContext();
// find entity by id
var invoice = dbContext.INVOICES.Find(this.CurrentInvoice.Id);
if (invoice.PAYED == 1) {
MessageBox.Show("The change is not possible, the invoice has already been paid.",
"Error");
return;
}
using (InvoiceEditorForm editor = new InvoiceEditorForm()) {
editor.Text = "Edit invoice";
editor.Invoice = invoice;
// Form Close Handler
editor.FormClosing += delegate (object fSender, FormClosingEventArgs fe) {
if (editor.DialogResult == DialogResult.OK) {
try {
// trying to save the changes
dbContext.SaveChanges();
// refresh
CurrentInvoice.Load(invoice.INVOICE_ID);
masterBinding.ResetCurrentItem();
}
catch (Exception ex) {
// display error
MessageBox.Show(ex.Message, "Error");
// Do not close the form to correct the error
fe.Cancel = true;
}
}
};
editor.ShowDialog(this);
}
}
Here we needed to find an entity by the identifier provided in the current record. The CurrentInvoice is used to retrieve the invoice selected in the grid. This is how we code it:
public InvoiceView CurrentInvoice {
get {
return (InvoiceView)masterBinding.Current;
}
}
Using the same approach, you can implement deleting the invoice header yourself.
Paying an Invoice
Besides adding, editing and deleting, we want one more operation for invoices: payment. Here is code for a method implementing this operation:
private void btnInvoicePay_Click(object sender, EventArgs e) {
var dbContext = AppVariables.getDbContext();
var invoice = dbContext.INVOICES.Find(this.CurrentInvoice.Id);
try {
if (invoice.PAYED == 1)
throw new Exception("The change is not possible, the invoice has already been paid.");
invoice.PAYED = 1;
// trying to save the changes
dbContext.SaveChanges();
// refresh record
CurrentInvoice.Load(invoice.INVOICE_ID);
masterBinding.ResetCurrentItem();
}
catch (Exception ex) {
// display error
MessageBox.Show(ex.Message, "Error");
}
}