Let’s now implement the logic necessary to save our friends
to a database.
Right now we are simply working against a plain-old C# class
(sometimes referred to as a “POCO” class - “plain old CLR (or C#)
object”). One approach we could use would be to write some separate
persistence code that maps this existing class we’ve already written to a
database. Object relational mapping (ORM) solutions like NHibernate support
this POCO / PI style of mapping today very well. The ADO.NET Entity
Framework (EF) that ships with .NET 4 will also support POCO / PI mapping, and
like NHibernate will also optionally enable the ability to define persistence
mappings in a “code only” way (no mapping file or designers required).
If our Person object was mapped to a database in this way
then we wouldn’t need to make any changes to our Person class or to any of our
validation rules – it would continue to work just fine.
But what if we are using a graphical tool for our ORM
mappings?
Many developers using Visual Studio today don’t write their
own ORM mapping/persistence logic – and instead use the built-in designers
within Visual Studio to help manage this.
One question that often comes up when using DataAnnotations
(or any other form of attribute based validation) is "how do you apply
them when the model object you are working with is created/maintained by a GUI
designer". For example, what if instead of having a POCO style
Person class like we’ve been using so far, we instead defined/maintained our
Person class within Visual Studio via a GUI mapping tool like the LINQ to SQL
or ADO.NET EF designer:
Above is a screen-shot that shows a Person class defined
using the ADO.NET EF designer in VS 2010. The window at the top defines
the Person class, the window at the bottom shows the mapping editor for how its
properties map to/from a “People” table within a database. When you click
save on the designer it automatically generates a Person class for you within
your project. This is great, except that every time you make a change and
hit save it will re-generate the Person class – which would cause any
validation attribute declarations you make on it to be lost.
One way you can apply additional attribute-based meta-data
(like validation attributes) to a class that is auto-generated/maintained by a
VS designer is to employ a technique we call “buddy classes”. Basically
you create a separate class that contains your validation attributes and
meta-data, and then link it to the class generated by the designer by applying
a “MetadataType” attribute to a partial class that is compiled with the
tool-generated class. For example, if we wanted to apply the validation
rules we used earlier to a Person class maintained by a LINQ to SQL or ADO.NET
EF designer we could update our validation code to instead live in a separate
“Person_Validation” class that is linked to the “Person” class created by VS
using the code below:
The above approach is not as elegant as a pure POCO approach
– but has the benefit of working with pretty much any tool or
designer-generated code within Visual Studio.