Chapter 8
Entity and Validation
Classes
TableofContents
Chapter 8 ....................................................................................................................... 8-1
Entity and Validation Classes ........................................................................................ 8-1
Entity and Validation Classes Defined ............................................................... 8-2
Validation Defined .............................................................................................. 8-2
A Simple Product Entity Class ................................................................ 8-3
Entity Base Class ............................................................................................... 8-5
Validator Class ................................................................................................... 8-6
Validator Class Files ............................................................................... 8-8
PDSAProperty Class ............................................................................ 8-12
Generated Validator Class ................................................................... 8-13
Using the Validator and Entity Classes ............................................................ 8-16
Validate Method ................................................................................... 8-16
CheckBusinessRules Method .............................................................. 8-18
[Link] Namespace Overview .......................................................... 8-19
Chapter Index................................................................................................... 8-20
Entity and Validation Classes
Entity and Validation Classes Defined
An Entity class contains properties with data that need to be validated. An Entity
class only contains properties. There are no methods in an Entity class. An Entity is
made to just hold data and be used as a source of data to populate a collection
class of data. For example, a Customer entity would contain properties such as
CompanyName, CustomerId, etc. A Product entity would contain properties such
as ProductName, ProductId, Cost and Price.
A Validation class is a class that knows how to check the data within the properties
of an Entity class. This validation class should be able to perform basic validation
such as; is the data in a property required to be filled in, should string data be a
minimum or maximum length, should a numeric value have a minimum or
maximum value. You should also be able to add more complex, specialized
business rules to your validation class.
Validation Defined
When a user inputs data you will most likely need to check that this data is correct.
There are a lot of various things you need to check on a particular piece of data.
Here are some rules that you might need to check.
1. Is the data required?
2. Should the string data be a minimum length?
3. Should the string data be a maximum length?
4. Should the numeric data have a minimum value?
5. Should the numeric data have a maximum value?
6. Should the date data have a minimum date?
7. Should the date data have a maximum date?
8. Any other custom rules.
Rules 1-7 are ones that can be checked with a standard set of methods. Any
custom rules you will, of course, have to write yourself. The purpose of the PDSA
Validation system is to help with all 8 cases outlined above.
The principle behind the validation system is the Entity class. An Entity class is
simply a class with a public property for each piece of data for which you need to
verify business rules. For example, if you have a product table as shown in Listing
1, you would most likely create a class with a public property for each column in
this table.
8-2
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
Validation Defined
CREATE TABLE [Link]
(
ProductId int IDENTITY(1,1) NOT NULL PRIMARY KEY NONCLUSTERED,
ProductName varchar(50) NOT NULL,
IntroductionDate datetime NULL,
Cost money NULL,
Price money NULL,
IsDiscontinued bit NULL
);
Listing 1: A Sample Product Table
A Simple Product Entity Class
An example class for representing the above Product table might look like Listing 2.
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
8-3
Entity and Validation Classes
[Link]
Public Class Product
Inherits PDSAEntityBase
Public Sub New()
ClassName = "Product"
End Sub
Private
Private
Private
Private
Private
Private
mProductName As String
mProductId As Integer
mIntroductionDate As DateTime
mPrice As Decimal
mCost As Decimal
mIsDiscontinued As Boolean
Public Property ProductName() As String
Get
Return mProductName
End Get
Set(ByVal Value As String)
mProductName = Value
End Set
End Property
Public Property ProductId() As Integer
Get
Return mProductId
End Get
Set(ByVal Value As Integer)
mProductId = Value
End Set
End Property
Public Property IntroductionDate() As DateTime
Get
Return mIntroductionDate
End Get
Set(ByVal Value As DateTime)
mIntroductionDate = Value
End Set
End Property
Public Property Price() As Decimal
Get
Return mPrice
End Get
Set(ByVal Value As Decimal)
mPrice = Value
End Set
End Property
Public Property Cost() As Decimal
Get
Return mCost
End Get
Set(ByVal Value As Decimal)
mCost = Value
End Set
End Property
8-4
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
Entity Base Class
Public Property IsDiscontinued() As Boolean
Get
Return mIsDiscontinued
End Get
Set(ByVal Value As Boolean)
mIsDiscontinued = Value
End Set
End Property
End Class
C#
public class Product : PDSAEntityBase
{
Public Product()
{
ClassName = "Product"
}
public
public
public
public
public
public
int ProductId { get; set; }
string ProductName { get; set; }
DateTime IntroductionDate { get; set; }
decimal Cost { get; set; }
decimal Price { get; set; }
bool IsDiscontinued { get; set; }
}
Listing 2: A Simple Product Entity Class
Each public property in the Product class corresponds to one of the columns in the
Product table. We are not going to talk about how you load data into this class as
there are many ways to accomplish that. In fact, this Product class does not even
have to be loaded from a table in a database, it could be loaded from data in an
XML file, or simply data read in from a user. This chapter will just focus on the
validation of the data within this Product class.
Entity Base Class
Each Entity class generated from Haystack will inherit from a base class called
PDSAEntityBase. It is a good idea to always have a base class as this lets you add
on additional properties to each entity, and maybe add some additional
functionality such as the INotifyPropertyChanged event if you will be using your
Entity class with WPF or Silverlight. The PDSAEntityBase class is shown in Figure
1.
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
8-5
Entity and Validation Classes
Figure 1: The Entity Base Class
The PDSAEntityBase class is an abstract class which means it may not be
instantiated. The entity classes you create, such as a Product class, will inherit
from this class. Notice that is has a ClassName and a PDSALoginName property.
These two properties will come in handy when dealing with inherited classes,
exception handling and keeping track of who last updated the Product class. The
PDSALoginName property is automatically filled in with the
[Link] property on the machine in which this assembly is running.
The other property is a IsDirty property which is set if you modify any property in
your entity class.
Notice that this class also implements the INotifyPropertyChanged interface and
defines a method called RaisePropertyChanged that may be called from the set
procedure in each property if needed.
Validator Class
Now that you have an entity class that can contain data in each of its properties,
you now need a class that will validate that data. There are a few reasons to
separate the data from the validation code for that data.
8-6
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
Validator Class
1. You want to be able to pass just the data across application boundaries,
such as when using WCF or Web Services.
2. You want the entity class to be able to be loaded from any data access
method.
3. You want to be able to re-use the validation code for different entity objects
in different applications
4. You want the ability to change the validation mechanism if needed.
Figure 2 shows an example of a ProductValidator class that needs to be created
for validating the data in the Product entity class.
Figure 2: The ProductValidator Class
While there is one class called ProductValidator, this class is actually split across
two different files. One file is used for generated code, and the other file is for
custom code that you will add to this class for your custom business rules.
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
8-7
Entity and Validation Classes
Validator Class Files
The ProductValidator and the [Link] files are used to
facilitate code generation and the separation of standard business rules from the
custom business rules you write. For example, if you are using a code generator
that can read schema information from the Product table shown in Listing 1, then
you can infer maximum lengths and whether or not fields are required. This
information can be written into a method in the [Link] file.
To help us with standard methods for verifying all of the business rules we listed at
the beginning of this chapter, the ProductValidator class contains a collection of
PDSAProperty objects. This PDSAProperty collection is defined in the
PDSAValidatorBase (Figure 3: The PDSAValidatorBase Class) from which the
ProductValidator class inherits. The collection will hold one PDSAProperty object
for each public property in the Product Entity class. The PDSAProperty class is
responsible for handling all the standard business rules identified in rules 1 through
7 defined at the beginning of this chapter.
8-8
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
Validator Class
Figure 3: The PDSAValidatorBase Class
The two main goals of the Validator class are to associate standard business rules
with the properties of the Entity class, and have a place for you to add your own
custom business rules. So, for example, if you want the ProductName property to
be required, have a minimum length of six, and a maximum length of 50, you would
set some properties in the ProductValidator class to reflect these rules. Listing 3
shows the ProductValidator class from the file where you add custom business
rules.
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
8-9
Entity and Validation Classes
[Link]
Partial Public Class ProductValidator
' The ValidateCore method is for custom rules
Protected Overrides Sub ValidateCore()
End Sub
' This method is for standard rules
Protected Overrides Sub AddBusinessRulesToProperties()
' Add any standard rules here.
'Dim prop As PDSAProperty
'prop = [Link]( _
[Link])
'[Link] = 6
'prop = [Link]( _
[Link])
'[Link] = [Link]("1/1/2000")
'[Link] = [Link]
End Sub
End Class
C#
public partial class ProductValidator {
// Constructor
public ProductValidator(Product entity) : base(entity) {
}
// The ValidateCore method is for custom rules
protected override void ValidateCore() {
// Write Custom Business Rules Here
if ([Link] < [Link])
[Link](
new PDSAValidationRule("Cost",
"Cost must be less than price"));
}
// This method is for standard rules
protected override void AddBusinessRulesToProperties() {
// Add any standard rules here.
PDSAProperty prop;
// Retrieve the ProductName property and set some rules
prop = [Link](
[Link]);
[Link] = true;
[Link] = 6;
// Retrieve the IntroductionDate property and set some rules
prop = [Link](
[Link]);
[Link] = [Link]("1/1/2000");
[Link] = [Link];
}
}
Listing 3: Add Rules using Properties and writing custom code.
8-10
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
Validator Class
The ValidateCore() method is where you write any custom business rules other
than the first seven listed at the beginning of this chapter. In the sample in Listing 3
you are verifying that the Cost is not greater than Price. If it is, you then need to
add the name of the property that failed the business rule, and a message to the
collection of business rule failures. You may have many failures, so once all of the
checking is done, you may access the collection of business rule failures and
report these back to the user in some fashion.
The AddBusinessRulesToProperties() method is where you can add rules that fit
into numbers 1 through 7 at the beginning of this chapter. You simply need to
retrieve the specified column/property that you are interested in and set the
appropriate property. To retrieve a property you need to reference it by name. For
this you will use the ColumnNames class that contains all of the property names in
the Product class expressed as a string. Listing 4 shows the definition of the
ColumnNames class for the Product class. This class is located in the
[Link] file.
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
8-11
Entity and Validation Classes
[Link]
Public Class ColumnNames
Public Shared ReadOnly Property ProductId() As String
Get
Return "ProductId"
End Get
End Property
Public Shared ReadOnly Property ProductName() As String
Get
Return "ProductName"
End Get
End Property
Public Shared ReadOnly Property IntroductionDate() As String
Get
Return "IntroductionDate"
End Get
End Property
Public Shared ReadOnly Property Cost() As String
Get
Return "Cost"
End Get
End Property
Public Shared ReadOnly Property Price() As String
Get
Return "Price"
End Get
End Property
Public Shared ReadOnly Property IsDiscontinued() As String
Get
Return "IsDiscontinued"
End Get
End Property
End Class
C#
public class ColumnNames
{
public static string ProductId = "ProductId";
public static string ProductName = "ProductName";
public static string IntroductionDate = "IntroductionDate";
public static string Cost = "Cost";
public static string Price = "Price";
public static string IsDiscontinued = "IsDiscontinued";
}
Listing 4: A ColumnNames class for the Product Entity Class
PDSAProperty Class
The PDSAProperty class has properties that you set to automatically check
business rules for the data filled into the Entity class. Instead of you having to write
8-12
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
Validator Class
all of the code to check for required values, min/max lengths, or min/max values,
the Validator class will set all of this up for you via a code generator. You may set
the properties listed in Table 1 for each property in your Entity class.
Property
Description
IsRequired
Is value required?
MinLength
The minimum length for a string value
MaxLength
The maximum length for a string value
MinValue
The minimum value for a numeric or date value
MaxValue
The maximum value for a numeric or date value
Table 1. The PDSAProperty Class Properties for business rules.
Generated Validator Class
Now, let's take a look at the generated portion of the ProductValidator class. Listing
5 shows an abbreviated form of the partial class ProductValidator. This class is
intended to be re-generated if you are using a code generator. So, if you were
generating from the schema of a table, and columns gets added or deleted, the
various properties, the ClassName class with the string representation of the
properties, and the business rules could be re-generated without affecting any
custom rules you have setup in the other file.
Take a look at Listing 5 and notice that the constructor calls InitProperties() which
is located in this file, and it calls the AddBusinessRulesToProperties() which is in
the other file.
The InitProperties() method is where you create new PDSAProperty objects and
add them to the Properties collection. There is a static/shared method named
Create() on the PDSAProperty class that allows you to set multiple validation rules
at one time. You can specify if a property is required or not, the data type and the
maximum length.
Notice the two other methods EntityDataToProperties() and
PropertiesToEntityData(). These methods are used to move data from the Entity
(Product) class into the properties collection and vice versa. Prior to performing any
validation the EntityDataToProperties is called.
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
8-13
Entity and Validation Classes
[Link]
Partial Public Class ProductValidator
Inherits PDSAValidatorBase
Public Sub New(ByVal entity As Product)
[Link]()
mEntity = entity
ClassName = "ProductValidator"
InitProperties()
End Sub
' The Entity Class Property
Private mEntity As Product
Public Property Entity() As Product
Get
Return mEntity
End Get
Set(ByVal value As Product)
mEntity = value
End Set
End Property
Protected Overrides Sub InitProperties()
[Link] = New PDSAProperties()
[Link]( _
[Link]([Link], _
"Product Id", True, GetType(Integer), 0))
[Link]( _
[Link]([Link],_
"Product Name", True, GetType(String), 50))
' THE REST REMOVED FOR SPACE
End Sub
Protected Overrides Sub EntityDataToProperties()
If [Link] Is Nothing Then
[Link]()
End If
[Link]( _
[Link]).Value = _
[Link]
[Link](_
[Link]).Value = _
[Link]
' THE REST REMOVED FOR SPACE
End Sub
Protected Overrides Sub PropertiesToEntityData()
If [Link] Is Nothing Then
[Link]()
End If
If [Link]( _
[Link]).IsNull = False Then _
[Link] = _
8-14
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
Validator Class
[Link]( _
[Link]).GetAsInteger()
End If
If [Link]( _
[Link]).IsNull = False Then_
[Link] = _
[Link]( _
[Link]).GetAsString()
End If
' THE REST REMOVED FOR SPACE
End Sub
End Class
C#
public partial class ProductValidator : PDSAValidatorBase {
public ProductValidator(Product entity) : base() {
Entity = entity;
ClassName = "ProductValidator";
InitProperties();
AddBusinessRulesToProperties();
}
// The entity class property
public Product Entity { get; set; }
protected override void InitProperties() {
[Link] = new PDSAProperties();
[Link](
[Link]([Link],
"Product Id", true, typeof(int), 10));
[Link](
[Link]([Link],
"Product Name", true, typeof(string), 50));
// THE REST REMOVED FOR SPACE
}
protected override void EntityDataToProperties() {
if ([Link] == null) {
[Link]();
}
[Link](
[Link]).Value = [Link];
[Link](
[Link]).Value = [Link];
[Link](
[Link]).Value =
[Link];
// THE REST REMOVED FOR SPACE
}
protected override void PropertiesToEntityData() {
if ([Link] == null) {
[Link]();
}
if([Link](
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
8-15
Entity and Validation Classes
[Link]).IsNull == false)
[Link] = [Link](
[Link]).GetAsInteger();
if([Link](
[Link]).IsNull == false)
[Link] = [Link](
[Link]).GetAsString();
// THE REST REMOVED FOR SPACE
}
}
Listing 5: The generated Validator class.
Using the Validator and Entity Classes
The Validator classes are designed to hold an instance of the Entity class. So you
must create an instance of an Entity class, fill that Entity class with data, and pass
that instance to the constructor of the Validator class. How you fill the Entity class
with data will depend on the circumstances. It could be filled from a user entering
data on a form, or you might read some data in from a database table.
Once you have created instances of these two classes, you may now perform the
validation. Remember, that the Validator class is where you will have setup the
standard business rules by setting the collection of PDSAProperty objects, and by
writing custom business rules in the ValidateCore() method.
Sample Solution: Validation_Sample_xx.sln is located in the
[InstallFolder]\Haystack\Samples\CSharp|VB\Validation_Sample_?? folder.
Validate Method
Listing 6 shows a sample of setting the ProductName property on the Entity class
to an empty string so you can see the results of failing the required test. To validate
the data within the Entity class you call the Validate() method. The Validate()
method is contained in the base class of the ProductValidator class. This method
checks all of the standard business rules by looping through the collection of
PDSAProperty objects, and calls the ValidateCore() method.
8-16
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
Using the Validator and Entity Classes
[Link]
Private Sub RequiredValidationHardCodedSample()
Dim prod As Product
Dim prodValid As ProductValidator
' Create ProductEntity Class
prod = New Product()
' Set ProductName to empty to fail the "Required" test
[Link] = [Link]
' Create Validator Class and Pass in ProductEntity Class
prodValid = New ProductValidator(prod)
Try
[Link]()
Catch ex As PDSAValidationException
[Link]([Link])
End Try
End Sub
C#
private void RequiredValidationHardCodedSample() {
Product prod;
ProductValidator prodValid;
// Create ProductEntity Class
prod = new Product();
// Set ProductName to empty to fail the "Required" test
[Link] = [Link];
// Create Validator Class and Pass in ProductEntity Class
prodValid = new ProductValidator(prod);
try {
[Link]();
}
catch (PDSAValidationException ex) {
[Link]([Link]);
}
}
Listing 6: Using the Entity and Validator classes
After calling the Validate() method, if any business rules fail, they will be added to a
collection within a PDSAValidationException object. You can report all of these
error messages back at once by using the ToString() method on this exception
object. By default, the error messages will be delimited with a CRLF from the
Message property. If you are reporting the messages back from within a web page,
you would call the [Link]() method. This method will replace
the CRLF with a <br /> tag.
Instead of getting all of the error messages back as a single delimited string, you
may also access each business rule failure by looping through the
BusinessRuleMessages collection on the PDSAValidationException object as
shown in Listing 7.
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
8-17
Entity and Validation Classes
[Link]
For Each item As PDSAValidationRule In [Link]
[Link]([Link])
[Link]([Link])
Next
C#
foreach (PDSAValidationRule item in [Link])
{
[Link]([Link]);
[Link]([Link]);
}
Listing 7: Looping through the validation rule exceptions
For more examples of business rule validation, check out the samples in the
solution: Validation_Sample_xx.sln. This solution has many different examples of
validation rules.
CheckBusinessRules Method
Instead of raising an exception you can have an enumeration returned from the
CheckBusinessRules() method. This method performs the same validation outlined
above, but returns an enumeration instead of raising an exception.
private void CheckBusinessRuleMethod()
{
Product prod;
ProductValidator prodValid;
prod = CreateNewProduct();
[Link] = [Link];
// Create Validator Class and Pass in ProductEntity Class
prodValid = CreateNewValidator(prod);
if ([Link]() ==
[Link])
[Link]("Passed");
else
[Link]("Failed" +
[Link] + [Link] +
[Link]());
}
8-18
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
[Link] Namespace Overview
[Link] Namespace Overview
All of the base classes for the code shown in this chapter come from the
[Link] namespace. This namespace contains many different classes as
shown in Figure 4.
Figure 4: The [Link] namespace
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.
8-19
Entity and Validation Classes
Summary
The [Link] system will help you simplify the process of validating data. It
will significantly cut down the amount of validation code you will need to write.
When used with a code generator, this process will be even more significantly
reduced.
Chapter Index
A
AddBusinessRulesToProperties Method, 813
B
BusinessRuleMessages Collection, 8-17
MessageForWebDisplay Method, 8-17
MinLength Property, 8-13
MinValue Property, 8-13
P
PDSA Validation Namespace Overview, 819
PDSAProperty Class, 8-12
PDSAValidationException Class, 8-17
PropertiesToEntityData Method, 8-13
CheckBusinessRules Method, 8-18
E
Entity and Validation Classes, 8-2
Entity Base Class, 8-5
Entity Class, 8-2
EntityDataToProperties Method, 8-13
G
Generated Validator Class, 8-13
H
Haystack Generated Business Rules, 8-2
I
InitProperties Method, 8-13
IsRequired Property, 8-13
M
MaxLength Property, 8-13
MaxValue Property, 8-13
8-20
S
Sample Product Entity Class, 8-3
U
Using Validator and Entity Classes, 8-16
V
Validate Method, 8-16
ValidateCore Method, 8-16
Validation Class, 8-2
Validation Defined, 8-2
Validation Properties, 8-13
IsRequired, 8-13
MaxLength, 8-13
MaxValue, 8-13
MinLength, 8-13
MinValue, 8-13
Validator Class, 8-6
Validator Class Files, 8-8
Validator Classes, 8-16
Haystack Code Generator for .NET
Copyright 2010-2011 by PDSA, Inc.
All rights reserved. Reproduction is strictly prohibited.