How to trap SQL2005 RI messages to show a nice message to the user?


Author
Message
Edhy Rijo
E
StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)
Group: StrataFrame Users
Posts: 2.4K, Visits: 23K
Hi Greg,

Once again, thanks for the inside, you are in the right spot about what I am going thru, after 20+ years working with VFP one day a very good friend of mine (also a VFP developer) pushed me to start learning .NET and we start buying books and kind of compete each other, but at some point, the only way to really push yourself to learn a whole new language and environment is to start with a serious small project, and I took this project which I could have finished it already in VFP, to learn .NET and after looking for a framework I decided to go with SF. 

I have been working with a VFP framework for over 10 years (the same framework) and you bet there are a lot of stuff I miss w00t so in order for me to keep focus on the project, learning the new tools, and trying not to ask too much dummy questions, I simply post my comments/request for things I believe can be improved in SF in the future (of course I hope is the near future :heheSmile and thanks to you and the others I am getting there one step at a time.

Edhy Rijo

Greg McGuffey
Greg McGuffey
Strategic Support Team Member (3.3K reputation)
Group: Forum Members
Posts: 2K, Visits: 6.6K
Well, I'm not sure that the framework could handle this situation correctly. As has been mentioned, there are a bunch of ways to handle this (ensuring that children records are deleted before deleting a parent record), including setting up the tables so you never have to do this sort of check. There is no way for the framework to know what particular approach you'd take, so any arbitrary solution would be limiting. So, instead the framework does allow for special cases. In this case there are at least three choices:



- sub class BusinessLayer, override OnBeforeDelete, which offers the best control

- handle the BeforeDelete event of the form

- Handle the BeforeDelete event of the BO

- ...more I'm sure



The trick is to understand how things work enough to get the right solution for your needs. Unfortunately, that just takes time and what you are doing right now...asking lots of questions (I should know, I've asked about a million BigGrin ). When I was starting out, I often felt the same...the SF framework should do _____ (fill in the blank). Often it was more I just didn't understand how easy all this subclassing makes things (plus all the other .NET goodness). I'm refactoring some code I wrote about 6 months ago...boy did I do things the hard way then. I'm sure in another six months, it will be the same again (although by then, I'll likely be in VS2008, with linq, so god help me! Wink ). Of course, many of your suggestions are excellent and given some more time, I'm sure we'll see the BO Mapper doing lots more work for us, etc.



So, don't get discouraged, it'll get better sooner than you think..you're working hard and asking the questions!



Good luck!

Greg
Edhy Rijo
E
StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)
Group: StrataFrame Users
Posts: 2.4K, Visits: 23K
Hi Larry,

Thanks for that information, I knew there should be a way to handle this with more control on the developer.  Unfortunately, I am pretty new to .NET and VB and at this time I am not sure I would be able to do a class like that wihout any sample code. 

So far for this small project I think I can handle this situation with my previous posted code, but I really would like to see SF taking your approach and enhance the framework to deal with this situation directly.

Edhy Rijo

Larry Caylor
Larry Caylor
StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)StrataFrame VIP (1.2K reputation)
Group: Awaiting Activation
Posts: 592, Visits: 3.7K
The approach I took to solving this issue was to subclass BusinessLayer. In my custom business layer I shamelessly lifted someone else's business rules code to create my own ConstraintRules. Whenever a delete is called on my business objects a CheckConstraintsOnCurrentRow event is raised that is handeled by CheckConstraintRules in my BO. Within the BO I have private methods that are used to check for possible constraint violations. If one is found I have a AddConstraintViolation method (which is very similar to AddBorkenRule Wink) that adds violations to the ConstraintViolation collection. The custom business layer fires a ConstraintViolation event if violations exist that contains the collection of violations which in turn contains the error (violation) message/s added by AddConstraintViolation method. I can either handle the ConstraintViolation event or the ConstraintViolation collection and present the user with a friendy message before SQL barfs out a not so friendly one.

While I try to use cascading deletes where ever possible there are a number of situations where that doesn't work. Adapting the business rules approach has worked out well for me.

-Larry

Edhy Rijo
E
StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)
Group: StrataFrame Users
Posts: 2.4K, Visits: 23K
Hi Greg,

I tried your suggestion, but the problem is that when entering into the form's BeforeDelete() event, the delete confirmation message is already shown, wich leads me to believe that this message is only displayed in the BO.

I ended up creating a form's public var:

Public CheckAutoShowDeleteConfirmation As Boolean = False

Then in the BO's BeforeDelete:

Dim LoopCounter As Integer = 0

For Counter As Integer = 1 To e.BusinessObject.ChildBusinessObjects.Count

     If e.BusinessObject.ChildBusinessObjects.Item(LoopCounter).Count > 0 Then

          e.Cancel = True

          Me.CheckAutoShowDeleteConfirmation = True

          Me.AutoShowDeleteConfirmation = False

          MessageBox.Show("To delete this Service Call you must delete all related records first.", "Record Delete Warning...", MessageBoxButtons.OK, MessageBoxIcon.Information)

          Exit For

     End If

     LoopCounter += 1

Next

Then in the Form's BeforeDelete:

If Me.CheckAutoShowDeleteConfirmation = True Then

     Me.CheckAutoShowDeleteConfirmation = False

     Me.AutoShowDeleteConfirmation = True

End If

This way, the AutoShowDeleteConfirmation will work if the end user wants to delete a record with no children and will get the confirmation first.



Edhy Rijo

Greg McGuffey
Greg McGuffey
Strategic Support Team Member (3.3K reputation)
Group: Forum Members
Posts: 2K, Visits: 6.6K
Edhy,



When you BeforeDelete event handler is called, the user has already confirmed or canceled the delete, so the line

Me.AutoShowDeleteConfirmation = False


is not going to do much at this point.



What you need to do is to set this in the designer for the form, the in your BeforeDelete, handle the confirmation for the user. So, the logic in you BeforeDelete would be:



- Check that all child objects are deleted (current logic, minus call to turn off AutoShowDeleteConfirmation)

- If any children found, show message (as your doing), cancel delete (as your doing), exit for, then exit handler

- If no children found, get confirmation from user that they want to do delete.

- If they cancel, cancel delete (e.cancel=true).



Hope that makes sense.
Edhy Rijo
E
StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)StrataFrame VIP (4.6K reputation)
Group: StrataFrame Users
Posts: 2.4K, Visits: 23K
Hi Ben,

Thanks for clarifications on this one.  I decided to handle this in the BO's BeforeDelete as follow, if you have any suggestion on how to improve this code, it will be greatly appreciated. Tongue

''' <summary>

''' Validate the Service Call before trying to delete it.

''' </summary>

''' <param name="e"></param>

''' <remarks></remarks>

Private Sub ServiceCallsBO1_BeforeDelete(ByVal e As MicroFour.StrataFrame.Business.BeforeDeleteEventArgs) Handles ServiceCallsBO1.BeforeDelete

     Dim LoopCounter As Integer = 0

     For Counter As Integer = 1 To e.BusinessObject.ChildBusinessObjects.Count

          If e.BusinessObject.ChildBusinessObjects.Item(LoopCounter).Count > 0 Then

               e.Cancel = True

               Me.AutoShowDeleteConfirmation = False

               MessageBox.Show("To delete this Service Call you must delete all related records first.", "Record Delete Warning...", MessageBoxButtons.OK, MessageBoxIcon.Information)

               Exit For

          End If

          LoopCounter += 1

     Next

End Sub



Edhy Rijo

StrataFrame Team
S
StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)
Group: StrataFrame Developers
Posts: 3K, Visits: 2.5K
The other option would of course, be to wrap the Save() call in a Try/Catch and test the SqlErrors collection on the InnerException of the thrown BusinessLayerException.  I believe the foreign key validation will have a specific error type you can test on.
StrataFrame Team
S
StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)StrataFrame Developer (4.2K reputation)
Group: StrataFrame Developers
Posts: 3K, Visits: 2.5K
Edhy,

Back to Paul's suggestion: You'll need to change the ErrorSavingMode to ContinueOnError before the ErrorSaving event will get fired.

On Greg's suggestion, it will work great, but you'll want to set the AutoShowDeleteConfirmation to False and show your own delete confirmation if the user is allowed to delete the message (because there are no children).

Greg McGuffey
Greg McGuffey
Strategic Support Team Member (3.3K reputation)
Group: Forum Members
Posts: 2K, Visits: 6.6K
Related to using BeforeDelete Event

The delete confirmation is handled by the SF form (BaseForm actually). This can be turned off at the form level (so no SF delete conformation is used). See http://forum.strataframe.net/FindPost11030.aspx for some more info.



I believe the events would be raised:



- OnBeforeDelete of BusinessLayer raises BeforeDelete event of the BO



- The BaseForm (which the SF StandardForm inherits from, which you form inherits from) handles this event, does the delete confirmation and raises form's BeforeDelete event.



- Any handlers you have added to the BeforeDelete event get fired (like the one you posted)...so confirmation has already happened at this point.



- Any handlers of the form's BeforeDelete event fires.



I think another option to have more control over this would be to handle it in a sub-class of BusinessLayer, then override the OnBeforeDelete method. The you have control over when the BusinessLayer raises the events in the first place. You could also add you own event that could fire when the child records aren't already deleted, then handle that event to provide the message.



MessageBox not working form within a BO

I know of no reason why you couldn't use MessageBox within a BO....it's just a class like any other (including Form classes). You might want to verify that the code is ever called by stepping through it.



Referential Integerity and Cascading Deletes

I also usually use referential integrity with cascading deletes. To setup this, you would setup the building address table to have a Foreign Key to the customers table with ON DELETE CASCADE set. This enforces that no building addresses can be added that don't have valid customers and that when a customer is deleted, any associated building addresses are deleted as well.



When the db is setup this way, then I usually turn off the auto confirmation of delete messages for the form and provide my own, so I can remind the user that any building addresses will be deleted as well (JC's idea of presenting how many would be deleted is a nice touch). This type of setup has a couple of advantages:



- it ensures that the db doesn't have any data in it...period

- it is simpler to implement (setup FK on table, override delete message)

- typically faster, as the db handles checking referential integrity and the cascading deletes very fast



Hope that helps! BigGrin

GO

Merge Selected

Merge into selected topic...



Merge into merge target...



Merge into a specific topic ID...




Similar Topics

Reading This Topic

Login

Explore
Messages
Mentions
Search