Using IValidator & Catching Exceptions

Posts   
 
    
AntonyG
User
Posts: 5
Joined: 17-Nov-2005
# Posted on: 17-Nov-2005 06:49:34   

Hi,

New to LLBLGen and loving it.

I'm having difficulty with one area though. Here's my scenario;

I'm using VS 2005 and using the LLBLGen adapter method. I've created a Validator class for my entity which implements the IValidator interface.

In my validator class, if something is not good, I'll throw a new ORMEntityValidationException exception.

I have a manager class which creates a data access adapter and calls the SaveEntity method. When I call the SaveEntity method, I cannot catch the ORMEntityValidationException exception. I have a Catch aa as ORMEntityValidationException and another Catch ex as Exception in my try block but neither catch the exception. The debugger tells me that the ORMEntityValidationException exception is not handled.

So, if first, before I call the SaveEntity method, I call the entity's validate method, I can catch the ORMEntityValidationException exception fine.

What I'm struggling with is do I really need to do an implicit call to the entity's validate method before executing the data adapter's SaveEntity method in order for me to catch the ORMEntityValidationException exception?

Since the SaveEntity method will call the entity's Validate method anyway, I end up going through the Validate method twice before I get to save.

What is it I'm missing?

Apologies if my explanation is a tad cryptic.

Regards Antony

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 17-Nov-2005 14:47:36   

Validate is called inside the SaveEntity() when the Entity to save is dirty.

please check thuis thread: http://www.sd.nl/TinyForum/Messages.aspx?ThreadID=4081 And if it doesn't solve your problem get back to us and send up code snippets

Good Luck

AntonyG
User
Posts: 5
Joined: 17-Nov-2005
# Posted on: 17-Nov-2005 23:23:28   

Hi, thanks for the reply. I think I'm on a different track though. I'll try and explain using code samples;

Using the adapater approach, I have a generated CustomerEntity class which I've coded a Validator class for.

Public Class CustomerEntityValidator
    Implements IEntityValidator

    Public Function Validate(ByVal containingEntity As Object) As Boolean Implements IEntityValidator.Validate

        Dim Customer As CustomerEntity = CType(containingEntity, CustomerEntity)

        Try
            If Customer.Title = "" Then
                Throw New ORMEntityValidationException("Customer Title is a required field.", containingEntity)
            End If
        Catch ValidationException As ORMEntityValidationException
            Throw
        Catch ex As System.Exception
            Throw
        End Try

    End Function

End Class

I have coded a manager class called CustomerManager that has a function called SaveCustomer. Here's the code (cut down) for it;

Public Function SaveCustomer(ByVal CustomerObject As CustomerEntity) As Boolean

    Dim myAdapter As New DataAccessAdapter

    Dim CustomerValidator As IEntityValidator = New CustomerEntityValidator
    CustomerObject.EntityValidatorToUse = CustomerValidator

    Try
        Return myAdapter.SaveEntity(CustomerObject)
    Catch ValidationException As ORMEntityValidationException
        Throw
    Catch ex as System.Exception
        Throw
    End Try

End Function

With the simple example above, if my Validator class (CustomerValidator) throws an ORMEntityValidationException exception, then it is not caught in the above "Try" block. The debugger tells me that the ORMEntityValidationException is not handled.

If I insert the following lines of codes in the above SaveCustomer function before the call to SaveEntity, I can catch the ORMEntityValidationException exception okay.

Try
     CustomerObject.Validate
Catch ValidationException as ORMEntityValidationException
     Throw
End Try

So functionally, I can acheive what I'm after by inserting an implicit call to Entity.Validate. But technically, this means I execute the Validate event twice because it's call by the Data Access Adapter also. I'd like to be able to catch the ORMEntityValidationException exception in my Try block that houses the call to myAdapter.SaveEntity so that the Validate method gets executed once only.

I appreciate the help. (Sorry about the lack of indentation on the code samples - can't figure out how to do that).

Kind Regards Antony

Paul.Lewis
User
Posts: 147
Joined: 22-Aug-2005
# Posted on: 19-Nov-2005 05:03:44   

Try this Validation class:


Public Function Validate(ByVal containingEntity As Object) As Boolean Implements IEntityValidator.Validate

Dim Customer As CustomerEntity = CType(containingEntity, CustomerEntity)

If Customer.Title = "" Then
   Throw New ORMEntityValidationException("Customer Title is a required field.", containingEntity)
End If

Return True
End Function

No need to catch and re-throw the general exception. If it occers it will bubble up on its own. Just throw the execption for the invalid attribute value.

AntonyG
User
Posts: 5
Joined: 17-Nov-2005
# Posted on: 23-Nov-2005 11:21:51   

Hi, thanks for your input.

I tried your suggestion. The debugger now breaks on the closing end-if where the ORMEntityValidationException is thrown in the Validator class with the message "ORMEntityValidationException was unhandled by user code".

Is it possible that the ORMEntityValidationException exception does not get caught in the SaveEntity method of the Data Access adapter?

As far as I can ascertain, the following events occur when saving an entity;

  1. Call to the data access adapter SaveEntity method.
  2. SaveEntity method uses Validator class to validate object.
  3. Validator class throws ORMEntityValidationException exception.

If I insert a .Validate call on the object prior to step 1 above, I can catch the ORMEntityValidationException exception in my code. But by doing so means I execute the Validate code twice prior to a save.

I feel like I may have missed some obvious concept here.

Kind Regards Antony

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 23-Nov-2005 14:54:25   

Exceptions should be easily catched.

Would you please try using a try/catch block without exception parameters in the catch.

try
{
     //your call to the SaveEntity()
}
catch
{
}
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 24-Nov-2005 12:45:22   

The exception thrown in a Validate method is to cause the transaction to roll back. It's not known if the entity Validate is called on is the first entity in the save queue. It can be it's the 4th (for example). This means that if there are already 3 saved and the 4th fails, the save action has to be aborted and the transaction has to be rolled back. The transaction can be created under the hood (for example if you save a single entity recursively, LLBLGen Pro will create a transaction for you). Without an exception this isn't possible, hence the exception.

Frans Bouma | Lead developer LLBLGen Pro
AntonyG
User
Posts: 5
Joined: 17-Nov-2005
# Posted on: 28-Nov-2005 12:25:53   

Hi,

Thanks for the info. That's cool, I understand the need for the exception and appreciate that any transaction in process would need to be rolled back in the case of validation failure.

My problem is that I cannot "catch" the exception (i.e. the ORMEntityValidationException) in my code unless I explicity call the entity .Validate method. In other words, I cannot catch the ORMEntityValidationException exception in my Save method which in turn calls the data access adapter's SaveEntity method without first calling the entity's .Validate method.

I tried using the suggested code from the previous post, i.e. just a try-catch-end-try block without catching a specific exception but that did not work - the debugger breaks and tells me that the ORMEntityValidationException exception is unhandled by user code.

As far as I can tell, this results in two calls to the .Validate method during a SaveEntity operation.

Kind Regards Antony

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 29-Nov-2005 13:02:22   

Could you elaborate a bit why you can't catch the ORMEntityValidationException? Because that should be catchable by code surrounding a Save call.

Frans Bouma | Lead developer LLBLGen Pro
AntonyG
User
Posts: 5
Joined: 17-Nov-2005
# Posted on: 30-Nov-2005 05:10:58   

Hi,

I have a "manager" class which handles the calls to the LLBLGen Data Access adapter. Within my manager class, I have a save method that issues the call to the SaveEntity method.

In the case that my Validator object finds some issue with the data, it throws a new ORMEntityValidationException exception.

At this point, my debugger environment breaks on the line after my Throw statement in the Validator class stating that the ORMEntityValidationException exception is not handled by user code.

The behaviour is such that it indicates to me that the SaveEntity method within the Data Access adapter has no try-catch-end-try block to catch the exception and throw it on. Although, I'm fairly certain that this is not the case.

Here's a step through of whats happing;

  1. My client interface issues a call to the manager class's Save method.
  2. With in the Save method of the manager class, it issues a Data Access adapter SaveEntity call which is enclosed in a try-catch-end-try block.
  3. The debugger breaks in the Validator class one line after issuing the Throw New ORMEntityValidationException statement with a message that the ORMEntityValidationException exception is not handled by user code.

If I add a try-catch-end-try block around my Throw statement in the Validator class, same thing happens except that it breaks at my Catch clause.

For now, I'm working around this by issuing an implicit call to Entity.Validate in my "manager" class Save method, then if Validation passes, I set the Entity.EntityValidatorToUse property to nothing since the object has already been validator and no need to be validated again by the SaveEntity method of the Data Access adapter.

Kind Regards Antony

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 30-Nov-2005 13:52:07   

All exceptions are bubbled upwards, so if you throw an exception inside the Validation method, the exception will end up in the code which called SaveEntity(), there's no other way. SaveEntity() has a try/catch/finally block, it catches all exceptions, rolls back a transaction (if applicable) and throws the exception again.

What I find particularly weird is that the debugger stops on the line after the throw. It should stop at the SaveEntity() call in your manager class.

Frans Bouma | Lead developer LLBLGen Pro