For production purposes, we occasionally have to “split” a manufacturing lot with two “child lots” pointing to the same “parent lot”. Each of those “child lots” can be split as well creating a linked tree of sub lots. These sub-lots then pass through the testing process and at the end they “finished quantity” is recorded but only for the sublot at the leaves of the tree (because those are the lots that actually make it to the end of the testing process). But when we are looking at our stock, we only want to look at the top level parent look and use that to determine quantities.
What I am trying to do is to traverse this tree of lots from the root to the leaves to essentially aggregate the finished quantities from all of the leaves. The issue is that I have no idea what the actual depth of the tree will be, so I cannot just defne a view that exposes all of the pertinent information for the whole tree. So my question is if there is some way to take a specific instance of an entity and reload its attrbiutes with a specified view. This way the view only needs to include one level of sublots and as I loop through each sublot beneath the root to get their finished quantities, I can reload the sublot to then see its sublots and so forth. I know I could do this with a DataManager.Load() with a LoadContext but I see that as somewhat clunky. Is there some built in functionality for this?
I think it’s a good use case for lazy loading provided by ORM: you just open a transaction, load your entity by EntityManager (without any view) and traverse its attributes at whatever depth. Until the transaction is open, ORM will load related attributes automatically. The only restriction is that you can run such code only on the middle tier.
What if I wanted to define this functionality as a @MetaProperty in my ManufacturingLot class definition? Am I able to create an EntityManager instance from my entity class? I am still a little fuzzy on what functionality is visible at what layer.
Hi, the code in your @MetaProperty should only deal with the business logic needed to calculate the aggregated quantity, and it will delegate the actual lazy-loading of missing attributes to the ORM.
In your specific case, it will navigate through the lots tree, starting from that entity instance and going deep, assuming to be always able to reach the leaves.
You cannot use an EntityManager in the entity’s code, because it is inaccessible by client tier code.
The advantage of having a MetaProperty though (instead of a service method e.g.) is that you can use that property directly in your UI components.
The downside of such a MetaProperty is that it will only work when the entity has been loaded via EntityManager with lazy loading enabled (what @knstvk mentioned in his reply) , but it will fail if loaded with DataManager with a view without the necessary depth.
It will simply throw a Cannot get unfetched attribute... exception in the latter case.
If you want to go that route, you should catch the error at the MetaProperty level, and return a special value (like -1) to indicate that it was not possible to calculate the actual quantity (you can turn it into a string like N/A).
But, as you see, it will start looking a bit “hacky”… probably a simple service method will do, and you can use some code in the controller to call that method and show the result in your UI (for example you can use a Table.ColumnGenerator to create a new column that calls into that service method).