Cancel Save / Validation

Posts   
 
    
BringerOD
User
Posts: 70
Joined: 15-Jul-2006
# Posted on: 16-Jul-2006 18:00:32   

How do I cancel the save in the validator class.

I dont want to throw an execption. What I want to do is just not continue with the save.

      Public Overrides Sub ValidateEntityBeforeSave(ByVal involvedEntity As IEntityCore)
          If 1=1 then
               CancelSave = True ' ??????
          end if 

         MyBase.ValidateEntityBeforeSave(involvedEntity)
      End Sub

Is there some variable to set that tells the save on the entity to cancel.

      Protected Overrides Sub OnBeforeEntitySave()
          If 1=1 then
               CancelSave = True ' ??????
          end if 

      End Sub

Same thing for the entity itself. I want to be able to cancel the save.

Bryan

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 16-Jul-2006 18:38:25   

The only option you have is throw an exception. The reason is that it has to cancel the transaction currently active, which can be deeply nested so an exception is the only safe remedy.

Frans Bouma | Lead developer LLBLGen Pro
BringerOD
User
Posts: 70
Joined: 15-Jul-2006
# Posted on: 16-Jul-2006 19:02:45   

That means I would have to have all my data routines in a try block.

This is not the best route for me.

damn, I was almost done. This might be the straw that breaks the back here.

rage

Otis wrote:

The only option you have is throw an exception. The reason is that it has to cancel the transaction currently active, which can be deeply nested so an exception is the only safe remedy.

BringerOD
User
Posts: 70
Joined: 15-Jul-2006
# Posted on: 16-Jul-2006 19:26:52   

Otis wrote:

The only option you have is throw an exception. The reason is that it has to cancel the transaction currently active, which can be deeply nested so an exception is the only safe remedy.

Maybe you can help me solve this.

Here is what we do when we save and validate data.

ASP.NET Page

  1. Load data to the controls from the business object
  2. User Edits Data
  3. User Submits Page - Saves Page
  4. On save routine we set the values from the page to the business object
  5. During the save of the business object any violation causes the object not to be saved to the database using a transactionscope object which is hidden in my custom business scope object.. Anytime there is not a complete called it obviously does not work.
  6. These violations are added to a collection of violations that are then used to report the errors to the user of the asp.net. This is done because we don’t want to continue to right user friendly violation errors in all of the gui front end forms or pages. Each business object which is very reusable has its violations written in a user friendly way. Basically added to a collection that is then formatted and displayed to the user if present.
  7. We display the errors using a common control that is on every page. We don’t have to write this code again ever. We just add violations in our business objects, if there are any. We also tie these into our user controls so we can show a red box around controls that have violated a rule. I wont go into that.
  8. If there are no errors, then a success is called on the screen to confirm to the user they did the right thing.

This is all done through a BusinessScope(Our internal singleton object that wraps the business object actions) that is only alive for the time of the business object transaction.

Here is an example of how we wrap the business objects code on the save of a page. I am in the middle of transferring our business objects to LLBL, but I need to be able to cancel the save without raising an exception. Exceptions are expensive anyway, but so are transaction scopes.

Anyway, I love the idea of LLBL, but I have not been able to figure out a way to get the below functionality.


         Using lBusinessScope As GEN.Sys.BusinessScope.BusinessScope = New GEN.Sys.BusinessScope.BusinessScope(New Web.BusinessScope.RoundTripRequest(DirectCast(Me.Page, CRMPage)))


            Me.mObjContentCallSchedule = New BAC.BL.CallSchedule

            If MyBase.EditObjectID > 0 Then Me.mObjContentCallSchedule.FillByID(MyBase.EditObjectID)

            Me.mObjContentCallSchedule.NameBind(Me.txtTitle)
            Me.mObjContentCallSchedule.DescriptionBind(Me.txtDescription)
            Me.mObjContentCallSchedule.MonthofYear = CType(Me.ddlMonth.SelectedValue, EnumMonthsOfYearFull)
            Me.mObjContentCallSchedule.Year = Me.ddlYear.SelectedValue
            Me.mObjContentCallSchedule.DisplayOrderBind(Me.txtDisplayOrder)
            Me.mObjContentCallSchedule.ObjectStatus = CType(Me.ddlStatus.SelectedValue, EnumObjectStatus)
            Me.mObjContentCallSchedule.Save()

            lBusinessScope.Complete()

            If Not GEN.Sys.BusinessScope.CurrentBusinessScope.HasViolations Then
               MyBase.EditObjectID = Me.mObjContentCallSchedule.ObjectID
            End If

         End Using


If this works a control we have on the master page, just displays a success in a standard section on the screen.

If there is a violation then the violations are displayed and the entire transaction is not commited.

Anyway, the only way for me to fit this in LLBL is to cancel the save, when I see violations, otherwise I do what, wrap every business object in a try catch, on the catch then do the test?

Bryan

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 16-Jul-2006 20:42:10   

BringerOD wrote:

That means I would have to have all my data routines in a try block.

This is not the best route for me.

damn, I was almost done. This might be the straw that breaks the back here.

rage

You've to anyway. What will you do when some exception occurs in the db? How will you terminate your transaction? You have to do that in a try/catch/finally block.

I'll look at your other post tomorrow.

Frans Bouma | Lead developer LLBLGen Pro
BringerOD
User
Posts: 70
Joined: 15-Jul-2006
# Posted on: 17-Jul-2006 05:46:49   

Otis wrote:

BringerOD wrote:

That means I would have to have all my data routines in a try block.

This is not the best route for me.

damn, I was almost done. This might be the straw that breaks the back here.

rage

You've to anyway. What will you do when some exception occurs in the db? How will you terminate your transaction? You have to do that in a try/catch/finally block.

I'll look at your other post tomorrow.

We trap unexpected exceptions globally, if they are expected we check for them and ovoid them.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 17-Jul-2006 11:00:41   

BringerOD wrote:

Otis wrote:

BringerOD wrote:

That means I would have to have all my data routines in a try block.

This is not the best route for me.

damn, I was almost done. This might be the straw that breaks the back here.

rage

You've to anyway. What will you do when some exception occurs in the db? How will you terminate your transaction? You have to do that in a try/catch/finally block.

I'll look at your other post tomorrow.

We trap unexpected exceptions globally, if they are expected we check for them and ovoid them.

Exceptions when a transaction occurs has to terminate the transaction locally. You can then bubble up the exception, that's up to you. Example:


try
{
    // start transaction
    // do transactional work, e.g. save, delete
    
    // all done, commit transaction
}
catch(Exception)
{
    // exception caught, rollback transaction here
    throw;
}
finally
{
    // dispose transactional object, e.g. DataAccessAdapter (adapter) or Transaction (SelfServicing)
}

Frans Bouma | Lead developer LLBLGen Pro
BringerOD
User
Posts: 70
Joined: 15-Jul-2006
# Posted on: 17-Jul-2006 19:16:13   

One of the main reason we don’t wrap everything in Try .. Catches is because we are minimalist. Less code means less code to maintain.

If there is a possibility that a section of code will cause a data exception we either test for it and avoid it, or we trap it. Most of the time we test for it.

Then all exceptions that are not expected, because it there were we would test for it, are them globally handled. In ASP.NET that would be the Global.asa, which is fixed for ASP.NET 2.0 so it can handle global exceptions better.

Anyway, its your framework, and if I want to use it, thems the rules I know. simple_smile

Bryan

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 17-Jul-2006 19:26:02   

BringerOD wrote:

One of the main reason we don’t wrap everything in Try .. Catches is because we are minimalist. Less code means less code to maintain.

If there is a possibility that a section of code will cause a data exception we either test for it and avoid it, or we trap it. Most of the time we test for it.

Then you will be bitten by it, guaranteed. You can't test for all possible errors an rdbms can throw at you. You have to protect your own code for dangling transactions that these are rolled back properly at the right time simple_smile

Then all exceptions that are not expected, because it there were we would test for it, are them globally handled. In ASP.NET that would be the Global.asa, which is fixed for ASP.NET 2.0 so it can handle global exceptions better.

Anyway, its your framework, and if I want to use it, thems the rules I know. simple_smile

It's not about handling exceptions, it's about anticipating on the fact that an exception occured and therefore you need to rollback the transaction and quit THERE. The caller then can decide to handle it and retry or leave it to a general handler if the exception is too severe.

Frans Bouma | Lead developer LLBLGen Pro
BringerOD
User
Posts: 70
Joined: 15-Jul-2006
# Posted on: 17-Jul-2006 20:04:15   

It's not about handling exceptions, it's about anticipating on the fact that an exception occured and therefore you need to rollback the transaction and quit THERE. The caller then can decide to handle it and retry or leave it to a general handler if the exception is too severe.

Well again I do things a bit differently, I wrap things in a transactionscope, which has to have run the complete command to commit the transaction, with the exception it never completes.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 17-Jul-2006 20:24:00   

ah, ok in that case (with sqlserver 2005, otherwise the transactions are expensive distributed COM+ transactions) I understand. It wasn't clear to me you were using System.Transactions' code simple_smile

Frans Bouma | Lead developer LLBLGen Pro
BringerOD
User
Posts: 70
Joined: 15-Jul-2006
# Posted on: 17-Jul-2006 20:26:28   

Otis wrote:

ah, ok in that case (with sqlserver 2005, otherwise the transactions are expensive distributed COM+ transactions) I understand. It wasn't clear to me you were using System.Transactions' code simple_smile

Sorry forgot to mention that, you mean when I write things down you can't read my mind, gosh!

simple_smile

Only works with SQL2005, 2000 would be expensive, agreed.