Business Rule Validation in a CSLA Blazor Application (Complex Object Graph) #4653
Replies: 2 comments 1 reply
-
I'm not offering an explicit answer, but I hope to offer some guidelines that you can apply to your specifics. I deal regularly with this kind of complexity, having to evaluate aggregate values or checking for conflicting values across lists of child records. I find that we always need a rule at multiple levels that are designed to satisfy the needs at each level. If a rule needs to compare between two children, the business rule should run at the level that can see all of the necessary information, but not at a higher level. We do this all the time with duplicate checking rules. The rule runs in the parent object above the list. For user notification, we apply an IsDuplicate property to the child class, which is set from the parent rule. The child class has a simple rule that sets the broken rule message when the IsDuplicate property is true. The parent rule isn't written as a CSLA business rule. Instead, it is initiated in a ChildChanged event handler. When the rule logic is strictly parent to single child, without the need to compare entries within the list, you can still follow the idea of a method in the parent that sets a status property on the child. I favor, however, using CSLA rule classes for this. For those relationships, we push the necessary parent properties to the children. That is, the child class includes a property to represent the parent property that is needed in the business rule. The child class has the core business rule that validates the proper relationship between the parent property and the child's property. A rule is used in the parent class to copy the parent property to the child class. We have this need so often that we have written a reusable rule. The constructor parameters are the primary property (from the parent class), the property info of the child object, and a string for the child property name. In the execute method, we check whether the child is a class or a list. When it is a class, we set the property through reflection (using CSLA helper methods). When it is a list, we loop the list and set the property via reflection on each item in the list. I find that these couple patterns apply to any kind complexity that we have encountered. |
Beta Was this translation helpful? Give feedback.
-
Thank @hurcane for the detailed explanation. Do you happen to have a representative example of what you are describing? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hello everyone,
I have a Csla class called BizdealEdit that can be either a Contract or a Purchase Order.
The BizdealEdit class has a list property called ListBizdealAnnexs, which contains objects of the BizdealAnnexEdit class. This is because a business of type "Contract" can have one or more annexes.
Each annex is linked to one or more clients, which is why the ListBizdealAnnexClients class has a Clients list property containing objects of the BizdealAnnexClientEdit class.
Each client in the annex is linked to one or more mining plants, so the BizdealAnnexClientEdit class has a list property called ListBizdealAnnexClientPlants.
Each plant in the annex and client contract is associated with one or more products or services that may be provided under the contract or purchase order. Therefore, the BizdealAnnexClientEdit class has an associated list called ListBizdealAnnexClientPlantItems, which contains objects of the BizdealAnnexClientPlantItemEdit class.
Finally, each object of the BizdealAnnexClientPlantEdit class has an associated task list called ListBizdealAnnexClientPlantItemTasks, containing objects of the BizdealAnnexClientPlantItemTaskEdit class, which represent the tasks required to produce the product or deliver the service.
On the other hand, the BizdealEdit class has a list property called ListProductionOrders, where the production orders associated with the contract or purchase order are stored. These are of the ProductionOrderEdit type.
The ProductionOrderEdit class, in turn, has two list properties:
ListProductionOrderItems – stores the items considered in the production order (of type ProductionOrderItemEdit).
ListProductionOrderDeliverys – stores the delivery orders (of type ProductionOrderDeliveryEdit) associated with the production order. A production order can have multiple deliveries.
The ProductionOrderItemEdit objects, in turn, have a list property called ListProductionOrderItemTasks, which stores objects of type ProductionOrderItemTaskEdit—these are the tasks to be performed for each item to be produced.
Similarly, the ProductionOrderDeliveryEdit class has a list property called ListProductionOrderDeliveryItems, containing objects of type ProductionOrderDeliveryItemEdit, which represent the actual products made or manufactured.
Finally, the ProductionOrderDeliveryItemEdit class has a list property called ListProductionOrderDeliveryItemTasks, containing objects of type ProductionOrderDeliveryItemTaskEdit, which are the tasks applied to the manufactured products.
I need to establish a BusinessRule that validates:
That the start and end dates of a ProductionOrderEdit fall within the start and end date range of the contract or purchase order.
That the amount and quantities to be produced by the new production order do not exceed the remaining balance of the contract (the total contract amount minus previous production orders) and the remaining quantities of products in the contract.
Where should I create this BusinessRule?
Should it be at the level of the BizdealEdit class or its child class ProductionOrderEdit?
How should this BusinessRule be structured?
How do I enforce the UI (Blazor) to execute these BusinessRules across the entire object graph, so the Save button is enabled/disabled based on MyBizdeal.IsSavable = false?
Any help would be greatly appreciated.
Thanks!
Beta Was this translation helpful? Give feedback.
All reactions