I would like you to review a part of my warehouse application, a Service Layer
to be exact. The architecture of the program is:
DB --> .Data (EF's DbContext/Entities) --> .ServiceLayer (Business) --> WCF services
I have Repo/UoW patterns implemented in Data (EF's DbConext has it built in). Basically nothing more. Raw DbSets and Entities. The whole magic is being done in Business layer obviously.
In Business layer I have implemented a bunch of Services, like PurchaseOrderService
or ReceivingService
. The thing is those services can be used by WCF Service directly AND by Business themselves. For example GetItemStatus
can be used by WCF Service with the same name "GetItmeStatus" OR it can be used by GetItemQuantity
service (because if the Item is Blocked, the Qty is 0). Let me post the code:
public class ItemService
{
IContextFactory ContextFactory { get; set; }
public ItemService(IContextFactory contextFactory)
{
ContextFactory = contextFactory;
}
public ItemStatus GetItemStatus(int itemId, WarehouseContext warehouseContext = null)
{
ItemStatus returnedItemStatus = ItemStatus.New;
//DBContext should be disposed only if it was created here, locally
bool shouldBeDisposed = (warehouseContext == null);
if (shouldBeDisposed) warehouseContext = ContextFactory.CreateWarehouseContext();
try
{
returnedItemStatus = warehouseContext.Items.Where(p => p.ItemId == itemId).Status;
}
finally
{
if (shouldBeDisposed) warehouseContext?.Dispose();
}
return returnedItemStatus;
}
public int GetItemQuantity(int itemId, WarehouseContext warehouseContext = null)
{
int returnedQuantity = 0;
//DBContext should be disposed only if it was created here, locally
bool shouldBeDisposed = (warehouseContext == null);
if (shouldBeDisposed) warehouseContext = ContextFactory.CreateWarehouseContext();
try
{
if (GetItemStatus(itemId, warehouseContext) != ItemStatus.Blocked)
{
returnedQuantity = warehouseContext.Items.Where(p => p.ItemId == itemId).Quantity;
}
}
finally
{
if (shouldBeDisposed) warehouseContext?.Dispose();
}
return returnedQuantity;
}
}
Of course, this example shows two methods from the same service. It's possible that one service will create another service and calls its function.
I would like you, to review the way I handle optional Context parameter, try finally
block instead of pretty using
block. This way, I don't have to create DbContext during every trip to the database. I can create a DbContext per Context. When I must get ItemStatus (ItemStatus only) from the WCF (or any other client) layer.. I can do it! and the DbContext will be created and disposed.
How do you like it? Thanks!