Ger Cannoll
|
|
Group: StrataFrame Users
Posts: 430,
Visits: 507
|
I have a Parent BO and a Child BO (using a Chikd Dialog) . I am at the point where I want to save the Parent and the child out to the Database and want to check the rules first. So I have code like: if (this.ParentBO1.CheckRules(true) && this.childBO1.CheckRules(true) ) { this.childBo1.Save(); this.parentBO1.Save(); MessageBox.Show("Document has been saved", "Kernel Software",MessageBoxButtons.OK, MessageBoxIcon.Information); }All works fine. But I want to put validation code into the Parent Business object which will be dependent on what's in the child buisness object. e.g. Particular Customers (on the Parent Bo) can only purchase certain Products (on the child BO). So at the stage I am validating the Parent BO, I need to loop through the Child BO . I would like to put this valididation code into the CheckRulesOnCurrentRow on the parent BO but am not clear on how I will access the Child Business Object on the Parent Business Object. ( It cant really be done from the ChildBO because the Customer could be changed after a whole pile of products have been added ).
|
|
|
Edhy Rijo
|
|
Group: StrataFrame Users
Posts: 2.4K,
Visits: 23K
|
Hi Gerard, Since you are using a ChildForm dialog, the StrataFlix application has a way to handle this in the ChildForm itself. Basically in the child form, you check for the childbo rules and if OK, then return OK, otherwise show a message to the user to fix the problem before exiting the child form, I do this all the time and works just fine, here is sample VB code for the cmdOK button: Private Sub cmdOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdOK.Click Dim validationResult As Windows.Forms.DialogResult With Me.BizTransactionItems1 '-- If the record has been changed, then validate the transaction If .IsDirty Then '-- If the Start Sequence is greater than zero, then validate the sequence is valid ' otherwise, validation will show an error message and wait for the correct sequence If .CardStartSerialNumber > 0 Then If Me.ValidateCardRecordData() Then validationResult = Windows.Forms.DialogResult.OK End If Else validationResult = Windows.Forms.DialogResult.OK End If Else ' -- No data has been changed, so just exit the form as if the user press the Cancel button. validationResult = Windows.Forms.DialogResult.Cancel End If If validationResult = Windows.Forms.DialogResult.OK Then '-- Make sure these fields are updated if they are empty. If String.IsNullOrEmpty(.QBCustomerRefID) OrElse String.IsNullOrEmpty(.QBInvoiceNumber) Then .QBCustomerRefID = Me.BizTransaction1.QB_CustomerRefID .QBInvoiceNumber = Me.BizTransaction1.QB_InvoiceNumber End If End If End With Me.DialogResult = validationResult End Sub In the above example I have a method ValidateCardRecordData() that will display a message if something is not valid.
Edhy Rijo
|
|
|
Greg McGuffey
|
|
Group: Forum Members
Posts: 2K,
Visits: 6.6K
|
Edhy's suggestion will work really well to check rules before returning to the parent BO. However, I think your process is a bit more complicated...
If I'm following your process, the business rule is something like: Given a customer in the parent BO, there is a defined set of products that can be ordered in the child BO. Given this rule, you would then need to apply it in two cases: when adding products to the child and if the customer changes on the parent. I'm also going to assume that while you definitely want to check the business rule, you also want to make your user experience better by limiting the products available when a customer is chosen and inform the user if their choice of customer will cause certain already ordered product to be removed from the child.
Here are some thoughts that might help you get going:
- First, I'd implement the rule in the child BO, because it is essentially a child BO rule: it controls what products are valid in that BO, but uses data from the parent. - I'd setup the parent BO so there is an event when the Customer changes (using the BO mapper). - I'd then handle the ParentBusinessObjectChanged event on the child BO and in that handler, set an event handler on the Customer changed event of the parent. This would call a method to check existing records in the child to make sure they are all still valid. This will need some way to allow notification of the user too (see next point). - I'd create an event on the child BO that is raised if products need to be removed after a customer on the parent is changed. The event args would provide info about the products being removed. I'd raise this event in the method that checks the existing rows of the child bo. - In the parent form, I'd handle this custom event and provide the user with info.
You might want to handle the Changing event of the Customers field on the parent, so you offer the user the choice to actually change the value if there are changes to the existing products. If you did this, you'd add a pair of events to the child BO, a "changing" one before you removed the offending products and an "changed" event after you remove the products.
This design allows you to enforce the business rule (via the standard CheckRules paradigm) and also allows you to automate the rule, independent of the UI. It also keeps the rule close to the appropriate data.
Hopefully I've understood the issue and this is helpful in getting you on you way with this issue.
|
|
|
Ger Cannoll
|
|
Group: StrataFrame Users
Posts: 430,
Visits: 507
|
Hi Edhy.
Just checking the ChildBo will not be sufficient in my case (Unless I can do it from the ParentBO).
Say my 'Logical' Business Rules stipulate that Customer 'A' is allowed Products 'X' and 'Y', and Customer 'B' is only allowed Proucts 'Z'. Customer A is input on the Parent BO..passes all validation. Products X and Y are input on the Child BO...pass all validation and focus passes back to the parent Form . Everything ok so far...........
Now , the customer is changed , on the parent form, from Cusrtomer 'A' to Customer 'B' . This now should not pass validation as Customer 'B' is only allowed product 'Z', ... but at this stage products 'X' and 'Y' have been entered on the Child BO.
What I am trying to do, is set up , on the Business Object , the Business Rule that Customer 'B' is only allowed Product 'Z'. My issue is how do I do this from within a Business Object, i.e. set up a Business Rule on say a Parent BO which will also require access to another BO (the child).
The scenario above is just one example, but the same would apply where 'Rules' will cross Business Objects. Another example would be where a date is entered on the Parent Business Object which might control what Product Discounts ara llowed. Initially , when the lines are being entered on the child, they will pass validation, but the problem may arise if the date is subsequently changed on the Parent, causing the child rules then to be broken
|
|
|
Ger Cannoll
|
|
Group: StrataFrame Users
Posts: 430,
Visits: 507
|
Hi Greg. Many thnaks for your very detailed and informative reply which gives me food for thought. - First, I'd implement the rule in the child BO, because it is essentially a child BO rule: it controls what products are valid in that BO, but uses data from the parent. My first inclination would be to do all the validation and rules in the Parent BO, as this is where the data will be saved from. In the example I have included only a scenario if the customer changes, but ther could be lots of other areas where something similar maight happen, e.g Any one of 3 dates could change, Reps could change, delivery codes could change etc...there could be upt to 10 fileds that might change that could have an effect on the child BO. If its possible, my preference would be to put all the Validation code into the Parent Buisness Object. Either way(whether I put it into the Parent or Child Business Object) how do I reference the instance of the other Business Object that I am validating i.e. If I am putting the code into the Parent BO, how do I refer to the Child Business Object Instance so I can check the data , or alternatively, if I put the code into the Child Business Object, how do I refer to the Parent Business Object in the BusinessRules checking code.
|
|
|
Greg McGuffey
|
|
Group: Forum Members
Posts: 2K,
Visits: 6.6K
|
Hi Gerald, I'd tend to be more modular. I.e. I'd likely have methods to enforce each of these rules and have each rule in the BO it is associated with. Then in the OnCheckRulesCurrentRow method, I'd call each of these rules. The reason is to decouple the data from the U.I. It also is better encapsulation, as each BO implements its own rules. By putting Child rules in the parent, you'd break this rule (but then sometimes ya just need to break the rules...so nothing is set in stone). This means that even if you edit the child data independent of the parent data, it's rules are still enforced. In other words I'd think of the this as a collection of rules, rather than one monolithic "rule". Also note that the checking of data validity of the child items when the parent customer value changes isn't really happening at the same time as other validity checks (in OnCheckRulesCurrentRow); it is happening when the parent field changes. All Business Objects have a ParentBusinessObject property. For this to work, you need to setup a parent relationship on the BO itself. Then on instances of a BO, you can set the ParentBusinessObject to an instance of the parent BO. There is also a ChildBusinessObjects property of a BusinessObject. If there is only one child BO, then this is easy, it's the item. This gets set when the ParentBusinessObject is set on a child. So, assuming you have both the parent BO and the Child BO on the form, and that you've configured the child BO's ParentRelationship and then set the ParentBusinessObject on the child instance on the form to the parent BO instance on the form, then: '-- From within parent BO, access Child BO (assume only one child) Dim childBO As MyChildBO = DirectCast(Me.ChildBusinessObjects(0), MyChildBO)
'-- From within the child BO, access the parent BO Dim parentBO As MyParentBO = DirectCast(Me.ParentBusinessObject, MyParentBO) Note that this code is in the BOs, but the ParentBusinessObject is set on the instance dropped on the form. Another approach would be to create a custom property on the parent for this specific type of child and program against that. Another long post. I hope it helps!
|
|
|
Ger Cannoll
|
|
Group: StrataFrame Users
Posts: 430,
Visits: 507
|
Hi Greg.
From the purist point of view I can sort of see what you are saying.. but it will take me some time just to get into that way of thinking.
I cannot find a property called ChildBusinessObjects in the Buisness Object Properties . Does this have to be input in code only ? Also, I would appreciate it if you could translate your code (with the DirectCast line) to C# as I cannot find a Directcast C# command and am not sure of what the equivalent is.
I want to put this code into the CheckRulesOnCurrentRow of the ParentBusiness object..... I will need to spend more time reviewing your earlier replies and consider moving code to the Child Business Objects and the various events
|
|
|
Greg McGuffey
|
|
Group: Forum Members
Posts: 2K,
Visits: 6.6K
|
Not sure why I did it VB.NET... DirectCast is a cast: MyChildBO childBO = (MyChildBO)Me.ChildBusinessObjects[0]; Yes, ChildBusinessObjects is code only. It is a List<BusinessLayer> property. You don't set the children, just access them. This list is filled via the setting of the ParentBusinessObject on the children. Again, if you have just one child, then it'll be easy. If you have more than on child BO at a time, then you'd just need to check the type. My ideas are just suggestions. There are many ways to get this done. You'll figure out what works for you. I'm just trying to point out some things I've learned along the way that have really helped improve my code.
|
|
|
Ger Cannoll
|
|
Group: StrataFrame Users
Posts: 430,
Visits: 507
|
Hi Greg
I have that working very well now checking the Child Business Object from the Parent. Many thanks for all your help.
I will definitely revisit this when I have a bit more time , and have a look at a more purist approach as per your suggestions
|
|
|
Greg McGuffey
|
|
Group: Forum Members
Posts: 2K,
Visits: 6.6K
|
Glad it helped and you have it working. I'll be glad to continue the discussion and hear what you'll have learned by then regarding where to put validation/business rules.
|
|
|