Wednesday, July 29, 2009

Complex DataAnnotations Validation Patterns Part 1

Source Code

2009-09-01 - I have updated the code to allow validated properties to be NonPublic so that you can implement the Unidirectional serialization property on the DataContext and HIDE the circular references but still validate them.

This page shows how to enhance the DataAnnotations functionality in the System.ComponentModel namespace and implement it in a LINQ to SQL ORM project observing a layered architecture. All the examples utilize the Northwind database.

Generate your .dbml and create partial class .vb files for all of your entities that need validation. We will be utilizing the System.ComponentModel.DataAnnotations.MetadataTypeAttribute on these classes to help with the fact that we cannot properly decorate the LINQ to SQL designer file classes.



An underlying issue with the ValidationAttributes is that the IsValid function takes just one parameter. This makes it impossible to easily do complex validations on the entity. In order to solve this problem we create an interface called IComplexValidationAttribute with a public member that will contain the System.Reflection.PropertyInfo for the property that is getting validated. This now allows us to know more about the property including wether or not its Nullable.

Here is a Validate function that accepts the entity itself and returns an List(Of ValidationException). It checks to see if the attribute is a IComplexValidationAttribute and if it is instead of passing the value of the property it passes the object itself and assigns the public PropertyInfo member. This allows us much more flexability when creating our own custom ValidationAttributes.



I have created a IComplexValidationAttribute called RequiredAssociation for help dealing with LINQ to SQL required foreign keys. It looks at the UnderlyingValue of the associated entity and also the storage column for the entity. If either of them are Nothing, 0, String.Empty, or Guid.Empty then the IsValid call returns false.

Another IComplexValidationAttribute called RequiredProperty should take the place of the regular Required attribute if a property allows NULL in the database but because of updates or changes in the business logic should be required. This attribute understands nullables, numerics, guids, and strings.

Now all you have to do is hookup to LINQ to SQLs partial subroutine for OnValidate.



Soon to follow part 2.

No comments:

Post a Comment