- Home
- LLBLGen Pro
- LLBLGen Pro Runtime Framework
Validation Guidance, How to Pass Status Information
Joined: 16-Sep-2005
Hello,
Looking for entity validation information, I came across this thread:
http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=4348
A short question about this as I am working on setting up my first project to use LLBLGen, using adapter templates.
I have arranged my BL to have a seperate 'Manager' assembly that wraps calls to and from the LLBLGen generic and db specific namespaces, similar to Frans' pet store port sample code.
I am trying to work out how to pass 'return' codes to and from the UI during validation checks.
For example, lets say that I have a routine called SaveCustomer in the Manager layer. This routine instantiates the data adapter and issues the daa.SaveEntity routine. It also has a .Validate routine that passes through a call to CustomerEntity.Validate.
I am planning to implement my business logic checks pertinent to this enitity using a custom validation object implementing IEntityValidator. Lets say that this routine does several checks: checks for duplicate customer, checks for customer having approved credit. If one of these fails, the validate should fail, and additionally if a save was attempted, it should fail.
The last message in the post from Frans indicates, and the documentation indicates, that I should raise a ORMEntityValidationException. This will allow the LLBLGen run-time to rollback any transactions and will raise an error to the calling routine, in this case, my SaveCustomer routine in the manager class. So, in this scenario, I would wrap the call to the CustomerEntity.Validate and daa.SaveEntity in try/catch and monitor for an error indicating that 1 of the 2 checks failed, at which point, I can decide how to then pass this information to the UI for handling.
Now, finally my questions.
-
From a code organization point of view, this concept of passing information back to the calling return via Exceptions, is great. The one point that I am having trouble accepting is the performance implications of using exceptions to pass status information about an entity? Looking at the Microsoft literature, although maybe that is my first mistake
, the recommended best practices for error handling indicate not using exceptions to pass 'information' back to calling routines, due to the performance impact that raising an exception causes? So, from the entity back to the calling routine, are LLBLGen user's typically using exceptions to pass 'status' back up to the calling routine?
-
Given #1 above, then how are people passing this status back up to the UI for handling, throwing another exception up to the UI, or return code's of some type. From a code organization perspective, the exception method is clean, but in this case, it causes 2 exceptions to be thrown. I find in debug mode, an exception causes a second or two delay as the CLR processes it. So in this case, I am causing a >=2 second delay to pass back to the UI that the customer name exists. Seems like a huge performance penalty just for using exceptions? Thoughts?
Thanks in advance. I hope someone with a bit more practical experience with LLBLGen can put me on the right path.
Can1
Joined: 16-Sep-2005
a small further piece of information. I just finished some testing in both windows and asp.net apps, raising an application exception. The performance delay that I am referring to in the prior post, occurs only for the 1st exception raised (4 second delay in my tests), each subsequently raised exception is almost instantaneous.
Given this, the performance concern that I had in the prior post might be OK, given that it appears to only occur on the 1st exception.
Anyone have any idea why this would be the case, first exception vs. subsequent that is?
I would still really like to hear if other people are using exceptions to pass 'status' back to calling routines through their validation classes?
Thanks for your time.
Can1
Joined: 26-Oct-2003
I believe I wrote a thread perhaps a year ago asking some of the same questions. I believe the response was that the exception that gets thrown is needed internally to bail out of the save process. The exception is one of the reasons I don't use the LLBLGen validation routines.
If you're going to use them, then I would catch the exception, extract the information and wrap it into a collection of "ValidationResult" objects which gets returned to the caller. My .02.
Jeff...
<EDIT> Found the thread. The exception is required to bail out of the transaction, not the entity's save.
Joined: 16-Sep-2005
Thanks for the insight Jeff, much appreciated. I am really 50/50 on whether using exceptions in this manner is bad practice or not. On the other hand, I would like to make use of the validation framework if possible. I will have to think about it more and do some testing before deciding which way to go.
Do you do all your validation before calling the llblgen save commands?
Thanks.
Can1
Joined: 05-Aug-2005
can1 wrote:
Thanks for the insight Jeff, much appreciated. I am really 50/50 on whether using exceptions in this manner is bad practice or not. On the other hand, I would like to make use of the validation framework if possible. I will have to think about it more and do some testing before deciding which way to go.
This is an interesting thread. As you say, best practices generally say that exceptions are for "Exceptional" errors. In other words, for things that you did not expect to occur. Like a connection couldn't be made to the server, or the hard drive ran out of space.
Exceptions should not be used for "expected" or non-Exceptional items. This to mean means business rule violations and validations of any kind.
One reason for this is performance I think. Another reason is control, since you don't have alot of control over the exception handling system.
That said, most business layers that I have seen raise exceptions when a business rule is violated. Or, the business layer will catch a DAL layer and throw a business exception with the DAL's exception message. So, it seems to be pervasive use of exceptions.
One exception (no pun intended) to this is the CLSA framework. It uses event notification system passing a broken rules collection (I think) that the UI layer can use to display messages to the user.
So, I guess it's up to you. This seems to be an exception handling world, and we just need to live in it.
BOb
Joined: 26-Oct-2003
I agree mostly with Mr. BOb. I try to keep exceptions to exceptional cases - cases which are unexpected, or not under user control, or difficult to control or predict. Validation and business logic errors do not fall under this category.
In regard to whether or not to use the LLBLGen Pro's validation framework, it's going to depend on how you've set up your application. If you've abstracted your business logic into a dedicated layer, then I would pull the validation and business logic out of the entities. If, however, you like keeping everything inside of the entities, then using the validation framework is probably your best bet as it is probably the safest option (it guarantees that the logic is called and validated before save).
There are a number of threads in the forums that discuss each BL approach and their relative merits.
I will say that keeping your validation outside of the entities offers some benefits. For example, if you have your validation logic available as a "rules engine", you now have the ability to validate any piece of data, whether it's in an entity context or not. If the validation logic is inside an entity, you're limited to only working with entities if you want validation. Can be problematic, especially if you're using datatables for grids like I am.
The other "issue" is that you don't have a consistent method of dealing with validation. For example, some types of validation or business rules require validation at higher levels than the entity, for example within a complete process, or even across the whole system. You'll still need to architect these, and having your field- and entity-level validation logic "trapped" inside the entity won't help. That's not to say that you couldn't use the IValidator implementations that get generated into the assembly outside of the entities. But you'll notice that, for example, the "Validate()" method only returns a boolean; no other information is available to pass back to the user. The point here is that you don't really have control over the validation if you use the framework's validation mechanism.
All of that notwithstanding, it's still a matter of personal need. Frans was good enough to include a basic validation framework within the system, including all code generation for all entities. Use it if it works well enough. You get strong guarantees with it, which is the most important thing for validation.
Hope that helps.
Jeff...
<EDIT> Ooop. Didn't really answer your question. Yes, I have a dedicated service layer that performs all validations before save.
Joined: 29-Oct-2005
What I did was create a generic attribute based validation framework. My business components utilize the controller/facade design pattern, so in my base business class, whenever a save is attempted, I recursively validate all the entities that are going to be persisted to the db. From a UI perspective, the developer is able to perform the following type of validation:
ClassValidator v = new ClassValidator(customerEntity);
if (!v.IsValid)
{
MessageBox.Show(v.GetBrokenRules());
}
Now, if a client by-passes the following check, I raise a business exception from the facade's base class.
Hope that helps.