Collections in the business layer

Posts   
 
    
Posts: 497
Joined: 08-Apr-2004
# Posted on: 21-May-2004 11:23:51   

Thanks for the forum area Otis wink

I thought I would enquire as to how people are handling collections within thier business layers. I am proposing that for our app tha we standardize to use DataTables (For the most part we only display collections in grids/reports etc).

Where it gets interesring is some places in my app allow the UI to add mutliple sub-items to a record. The BLL needs to be able to persist these in a PL friendly way - I am unsure whether my entitiy classes (e.g. customer) should contain collections e.g. "Customer Orders", and if so whether to implement these as datatables or for example an array of classes..

That way, the PL would work like this:


ent = entManager.Load(1)
ent.Orders = entManager.LoadOrders(ent); // To save loading them if I don't need 'em
ent.Orders[0].Amount = 10.0; // Update the order amount
entManager.SaveOrders(ent); // Just save the orders for the entity

Alternatively I could just have a "Customer" entity and a "CustomerOrder" collection in isolation, and pass both to "CustomerManager.Save()" This would look like this:


collOrders = entManager.LoadOrdersForCust(1)
collOrders[0].Amount = 10.0; // Update the order amount
entManager.SaveOrders(collOrders); // Just save the orders for the entity

I suppose my question in a nutshell is: Should my data class (entity) represent just a single item, or also all sub-collections that belong to it?

wayne avatar
wayne
User
Posts: 611
Joined: 07-Apr-2004
# Posted on: 21-May-2004 11:44:45   

Me Again!!

OK if you want to pass custom entities around - i would go with option 1 - I think? confused

entManager should not include a whole lot of get methods - rather get specific and let entManager be a CustomerManager dealing with all customer related issues and processes. When dealing with order specific issues create an OrderManager.

Wayne

Posts: 497
Joined: 08-Apr-2004
# Posted on: 21-May-2004 11:58:34   

I'm not surprised your wife was in a bad mood with you - you're always in these forums wink hehehe.

Thanks for the advice - you're right I should have a OrderManager, it was a bad example. My CustomerManager can then call it to save the orders, so it controls the transaction.

Ok, so say I want to update both the customer and the orders. Should the PL just call "custManager.Save(ent)", and leave the manager to save the customer, and then call the orderManager to save the orders. Or should the PL do:


custManager.save(ent)
ordersManager.Save(ent.Orders)

Probably the former, right?

If I did use collections within my entities, I wonder if I should take the easy route and use datatables... although that limits what I can do with them....

wayne avatar
wayne
User
Posts: 611
Joined: 07-Apr-2004
# Posted on: 21-May-2004 12:14:38   

although limits what I can do with them....

That is why most people use the the manager that exposes a list - collection, dataset, datatable or what ever and does the actual editing via 1-1 properties in the Manager - this way you don't have to edit records in a collection / array.

ent = entManager.Load(1)
ent.Orders = entManager.LoadOrders(ent); // To save loading them if I don't need 'em
ent.Orders[0].Amount = 10.0; // Update the order amount
entManager.SaveOrders(ent); // Just save the orders for the entit

This could be done like this.


Orders = OrderManager.LoadOrders(CustomerNo)
For I = 0 tp Orders.Count 
  OrderMan = OrderManager.LoadOrder(i)
  OrderMan.Order.Amount = 10.0; 
  OrderMan.Save()
end for

But as you can see the code above is a process. So it should be inside your BL like this.


OrderMan = new OrderManager()
OrderMan.SetOrdersAmountTo(Amount) 

Wayne

Otis - if you are reading this the Code and Quote function does not seem to work any more - it keeps on adding the tags to the end of the message? Is it because i switched to netscape? It would be nice if the new message link opened in a new window so i could refer back to the threads comments. Thats why i moved to netscape so i could use the tabs.

Posts: 497
Joined: 08-Apr-2004
# Posted on: 21-May-2004 12:20:05   

Thanks! I was editing my post as you answered, but thats OK, I didn't change much so your reply is still valid!

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39752
Joined: 17-Aug-2003
# Posted on: 21-May-2004 12:46:36   

Otis - if you are reading this the Code and Quote function does not seem to work any more - it keeps on adding the tags to the end of the message? Is it because i switched to netscape? It would be nice if the new message link opened in a new window so i could refer back to the threads comments. Thats why i moved to netscape so i could use the tabs.

No, that's the LR(1) parser going bezerk. The grammar contains a shift/reduce conflict, most of the time this is no problem, but sometimes you run into it. disappointed The parser has to be converted to an LL(1) parser like the TDL parser, which uses local context and is flexible with ambiguistic grammar.

Frans Bouma | Lead developer LLBLGen Pro
netLearner
User
Posts: 150
Joined: 18-Oct-2003
# Posted on: 21-May-2004 18:28:07   

Thanks to Wayne.

Posts: 497
Joined: 08-Apr-2004
# Posted on: 21-May-2004 23:51:34   

Thanks wayne, I think then that the code I would have goes like this:


entCustomer = CustManager.Load(8)
collOrders = OrderManager.LoadOrders(entCustomer.ID)
For I = 0 to Orders.Count 
entOrder = OrderManager.LoadOrder(Orders[I].ID)
entOrder.Amount = 10.0; 
OrderManager.Save(entOrder)
end for

In this example the manager gives me the collection of orders, rather than it being a collection on the customer entity, does this seem right? Just to clarify, the alternaitive would be:


entCustomer = CustManager.Load(8)
entCustomer.Orders = OrderManager.LoadOrders(entCustomer.ID)
For I = 0 to entCustomer.Orders.Count 
entOrder = OrderManager.LoadOrder(Orders[I].ID)
entOrder.Amount = 10.0; 
OrderManager.Save(entOrder)
end for

Both sets of code avoid passing back multiple entities to save, but arrange the data differently.

Posts: 497
Joined: 08-Apr-2004
# Posted on: 22-May-2004 00:15:29   

Actually, the more I think about this the more confused I get:

Our application will sometimes allow the user to add multiple things to a record before saving them. Continuing with the custmer/order example, the web page might allow the user to add mutliple orders to a customerorder page (maybe some client-side code adds orders to a "grid" of some sort). When the user hits "Save", the presentation logic jumps into life and wants to save all of the new orders added for the customer.

So, what does it do? I want to avoid wrting "BL" code in this layer, and I def. want to avoid transaction stuff, so I ideally want to just say:


entCustomer.Orders = Page.Orders 
Alternative:
collOrders = Page.Orders

This code is very high level, I would actually need to transform the page orders from a datagrid into for example a datatable before I can add it to my entCustomers.Orders.. Anyway, once the presentation layer has "populated" the entity, I need to call my BL to do the rest, so I call:


OrderManager.SaveOrders(entCustomer) // This passes the customer and orders
Alternative:
OrderManager.SaveOrders(entCustomer.ID, collOrders) // Pass the cust ID and orders

So, would the SaveOrders method do something like this:


public void SaveOrders(CustEntity entCust)
{

OrderManager.DeleteExistingOrders(entCust.ID); // Wipe what we already have assuming that this is OK

for i=0 to entCust.Orders.Count
     entOrder = entCust.Orders(i)
     OrderManager.Save(entCust)
next
}


Sorry for the loads of code, but I don't want to miss something obvious or over-complicate things!!

wayne avatar
wayne
User
Posts: 611
Joined: 07-Apr-2004
# Posted on: 22-May-2004 00:51:14   

Arn't you suppose to be sleeping? Look at the time! wink

If you are not dealing with a add one record then post back sinario i would say that your example looks correct

public void SaveOrders(CustEntity entCust)
{

OrderManager.DeleteExistingOrders(entCust.ID); // Wipe what we already have assuming that this is OK

for i=0 to entCust.Orders.Count
entOrder = entCust.Orders(i)
OrderManager.Save(entCust)
next
}

Why are you deleting the existing orders? confused

Posts: 497
Joined: 08-Apr-2004
# Posted on: 24-May-2004 09:53:31   

Sleep, whats that? wink

Thanks - its good to know my code makes some sense!

Don't worry about the deleting of existing orders, thats just there because its commonplace in our existing app, a lot of our methods maintain "link table data" with this general pseudo-code:

  1. Delete everything related to the "master"
  2. Add everything releated to the master from this page

Its quick 'n' easy !!