I am currently refactoring a WPF application that is built on the principles of the Repository Pattern
. It uses Entity Framework
as its ORM, and is Database First. Each of those entities is wrapped by Repository
, the interfaces of which are then used in Unit Of Work
. Those units of work are then used by ViewModels
.
However, a single transaction like, say, CreateInvoice()
affects several tables. For example, CreateInvoice()
would insert a Sale
record in Sales
Table, deduct available stock in Stock
Table, and so on and so forth. Here is a sample code for that:
public void Commit(IContainInvoiceInfo InvoiceInfo)
{
_invoiceInfo = InvoiceInfo;
try
{
_uow.BeginTransaction();
InsertInSalesTable();
UpdateCurrentStock();
UpdatePacketStock();
InsertStockHistoryEntries();
InsertInTaxTable();
_uow.Complete();
_uow.EndTransaction();
}
catch (Exception ex)
{
_uow.RollBack();
throw ex;
}
}
private void InsertInSalesTable()
{
_uow.salesrepo.Add(new Sale
{
ID = _invoiceInfo.InvoiceNum.ToString(),
client = _invoiceInfo.SelectedClient.ID,
saledate = _invoiceInfo.InvoiceDate,
totalvalue = _invoiceInfo.GrandTotal,
purchaseorder = string.IsNullOrWhiteSpace(_invoiceInfo.PONumber) ? null : _invoiceInfo.PONumber + "dated: " + _invoiceInfo.PODate.ToString("dd-MM-yy")
});
}
...
So, basically, ViewModels are doing the heavy-lifting of properly inserting data into the proper tables in a database.
The problem is that since I am using Entity Framework DB First
approach, the model generated is an anaemic one. They are simple data classes with absolutely no behaviour.
I could encapsulate this logic in the Unit Of Work
itself, or even create stored procedure in the database itself, or create a separate service layer which would consume the Units of Work and then make the ViewModels use the services instead of the Units of Work.
Which is the correct place to encapsulate this insertion/update logic?
Caliburn.Micro
for that purposeInsertInSalesTable
should probably never existed in the first place if you used bidnings, because you would have aSale
object bound and filled from UI optionally inserted in an EF-backed collection through aICommand
~yourCommit
.string
andObservableCollection
(BindableCollection
because I'm using Caliburn). Creating a Sales object from those input data is done inside theICommand
.