Wednesday, April 8, 2009

Simple, but robust business logic using Metadata in ADO.NET Entity Framework

ADO.NET Entity Framework

Please check out my previous post called Finally, ASP.NET validation the way it should be that describes why and what ADO.NET Entity Framework does, and why you should use it. Here, I will be showing how to implement metadata for an entity and some of the great attributes that are available to specify your business logic in an easy to use manner.

If you have not already, you will need to have added the ADO.NET Entity Data Model to your project, and add the table you want to model to it.

Since, the Entity Data Model uses partial classes (one for the generated code, and one that you can optionally create) we can write all our custom logic in an our own entity. Let's assume you have an Entity called Person. Just create a new class called Person in the same project and namespace as your ADO.NET Entity Data Model. Then add the partial keyword and this will automatically wire your new partial class up to the generated partial class.

That would look something like:

public partial class Person {}

Next we need to create a class that describes the metadata we want to add for the Person class. I recommend putting it in the same file as the Person partial class you created earlier. That would look something like this, though the name is not important:

public class PersonMetaData.{}

Now, we need to tell the Entity Framework where to find the metadata for the Person table. To do this we use an attribute on our Person class like this:

[MetadataType(typeof(PersonMetaData))]
public partial class Person {}

Now, I can use attributes to describe my metadata. Here is an example of what your Person.cs file may look like.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;

using System.ComponentModel.DataAnnotations;

namespace DataModel
{

[MetadataType(typeof(PersonMetaData))]
public partial class Person {}

public class PersonMetaData
{
[Range(1,150)]
[DisplayFormat(DateFormatString = "{0:###}", ApplyFormatInEditMode=true)]
public object Age;

[DisplayFormat(DataFormatString="{0:yyyy-MM-dd hh:mm}", ApplyFormatInEditMode=true)]
[DataType(DataType.DateTime)]
public object Birthday{ get; set; }
}

}


There are lots of attributes that can be added to describe the meta data. You can even create your own (they are easy to do). The attributes, are located in the System.ComponentModel.DataAnnotations namespace (also its own assembly). It is interesting to note that this is not in the web namespace. This means it can be used in other presentation layers.

Here is a list of the available built-in attributes:

  • DataType - Allows you to specify that this field is a certain kind of data that is more specific than the database types. For example, you can specify that the data is an email or date only. See the DataType enumeration for a complete list of supported datatypes.
  • DisplayColumn - Applicable when a column in a table contains a foreign key, Dynamic Data infers the display value for that column from the referenced table. By default, the first column of the referenced table whose type is string (or text) is used. If you want to use a different column use this attribute to override this behavior.
  • DisplayFormat - Allows you to specify a format for the data. For example: "{0:C}" for currency, "{0:d}" or {0:yyyy-MM-dd}" for date
  • Range - Allows you to restrict teh value to a numeric range. For example, value must be between 1 and 100 or even a date range.
  • RegularExpression - Allows you to specify what regular expression the value must match in order to be considered valid. For example, @"^[a-zA-Z]*$" to allow only alpha characters
  • Required - Allows you to indicate that a field is required. Allows you to specify a custom error message if you prefer also.
  • ScaffoldColumn - Allows you to exclude a field from the scaffolding. This is useful for not including auto-generated primary key fields when using Entity Framework.
  • ScaffoldTable - Allows you to exclude or include tables from being scaffolded.
  • StringLength - Allows you to limit the number of characters in a field.
  • UIHint - Allows you to specify the user-defined control to use to display the data field when you are using Dyanmic Data controls. See http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.uihintattribute.aspx for an in-depth example.

    For more info see:
    http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx

No comments: