Entity framework 4 – Part 5 – Validation using Data Annotations

This post is part of a series of post where I cover different aspects of the new version of Entity framework and the CTP features. I do focus on creating a POCO solutions, hence I don’t use the designer to generate my model.

Part 1 – Getting started
Part 2 – Relationships between non public members
Part 3 – Adding pluralization support to a non strongly typed ObjectContext.
Part 4 – Autoregister Entitymappings

Download the code.

This time I will look at validation using the “System.ComponentModel.DataAnnotations” lib. NOTE! That it doesn’t say “System.Data.Entity.DataAnnotations” or any other specific part of the .Net framework. It is a common lib that could be used in e.g ASP.Net MVC.

Specify the rules
Lets start with the rules. I have chosen to decorate my entities with attributes to specify the rules for them. This is as easy as:

1. Add reference to “System.ComponentModel.DataAnnotations”
2. Import namespace
3. Start decorating your classes.

This looks like:

[Serializable]
public class UserAccount
    : Entity
{
    [Required(AllowEmptyStrings = false, ErrorMessageResourceName = "UserAccountRequiredUsername", ErrorMessageResourceType = typeof(ModelValidationMessages))]
    public virtual string Username { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessageResourceName = "UserAccountRequiredPassword", ErrorMessageResourceType = typeof(ModelValidationMessages))]
    public virtual string Password { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessageResourceName = "UserAccountRequiredEmail", ErrorMessageResourceType = typeof(ModelValidationMessages))]
    public virtual string Email { get; set; }
}

I have not created any custom attribute to take care of specific validation like an “EmailAttribute”, but it can be done. I have chosen to go with resources, but you can go with simple errormessages which would look like:

[Required(AllowEmptyStrings = false, ErrorMessage="You must provide an username.")]
public virtual string Username { get; set; }

Validate an entity
In this example I’m performing the validation in my services. This is something that isn’t necessary. E.g if you are using the new MVC 2 the default modelbinder can handle the validation for you.

To fulfill “DRY” (Dont repeat yourself) I have created a base class for my services, which contains a helper-method that validates entities. The method is “ValidateEntity”. It returns an instance of my EntityValidationResult-class which contains the violations. I’m using this instance to determine if the entity should be persisted or not. The violations are passed back to the serviceconsumer via a ServiceResponse, so I don’t throw any ugly business exceptions.

public class SecurityService : Service, ISecurityService
{
    public SecurityService(IEntityStore entityStore)
        : base(entityStore)
    {
    }

    public ServiceResponse<UserAccount> SetupNewUserAccount(UserAccount userAccount)
    {
        var validationResult = ValidateEntity<UserAccount>(userAccount);

        if (!validationResult.HasViolations)
        {
            EntityStore.AddEntity(userAccount);
            EntityStore.SaveChanges();
        }

        return new ServiceResponse<UserAccount>(userAccount, validationResult);
    }
}

The ValidateEntity method is really simple, since it just consumes another object, my EntityValidator. The code for this looks like:

In the baseclass: “Service”:

protected EntityValidationResult ValidateEntity<T>(T entity)
    where T : IEntity
{
    return new EntityValidator<T>().Validate(entity);
}
public class EntityValidator<T> where T : IEntity
{
    public EntityValidationResult Validate(T entity)
    {
        var validationResults = new List<ValidationResult>();
        var vc = new ValidationContext(entity, null, null);
        var isValid = Validator.TryValidateObject(entity, vc, validationResults);

        return new EntityValidationResult(validationResults);
    }
}

The EntityValidator just consumes classes found in the System.ComponentModel.DataAnnotations library and returns eventual violations by wrapping them in my EntityValidationResult-class.

[Serializable]
public class EntityValidationResult
{
    public IList<ValidationResult> Violations { get; private set; }
    public bool HasViolations
    {
        get { return Violations.Count > 0; }
    }

    public EntityValidationResult(IList<ValidationResult> violations = null)
    {
        Violations = violations ?? new List<ValidationResult>();
    }
}

Handle the violations
Since I’m just fiddling a bit I have a simple consoleapplication which only outputs the errors:

private static void IfFailedServiceOperationInformUser<T>(ServiceResponse<T> serviceResponse)
{
    if (serviceResponse.Status == ServiceResponseStatuses.Succeeded)
        return;

    Console.WriteLine("Service failed!");

    if (serviceResponse.ValidationResult.HasViolations)
    {
        Console.WriteLine("Violations are:");
        foreach (var violation in serviceResponse.ValidationResult.Violations)
        {
            foreach (var member in violation.MemberNames)
                Console.WriteLine("\t+" + member);

            Console.WriteLine("\t" + violation.ErrorMessage);
        }
    }
}

Thats it for now. As always you can download a complete example, which has evolved since part 1 of this post-series.

//Daniel

8 thoughts on “Entity framework 4 – Part 5 – Validation using Data Annotations

  1. Pingback: Entity validaton using Custom Data Annotation attributes « Daniel Wertheim

  2. Why can’t the EF generate the validation data annotations for you? Required and max length are determined by the DB and known by EF and should be generated!

    • Yes it’s possible but Why should they be generated? I like to define my conceptual model of the domain in the code, and that’s where I want the rules.

      //Daniel

  3. You want the rules in the domain, but the rules in fact are in the database. Your column has a maximum width. Your column has a definition of whether it is nullable or not. You may choose to write your own rules in your domain and pretend that’s all you have to do, but then you are responsible for making sure they are in sync with the database. Sounds like work to me.

    You said it is possible to generate the data annotations… how so? I do not see how it is done.

  4. I am using EF to generate the model, no POCOs.
    Is there a way I can wire it up with DataAnnotations as well, e.g. by using Metadata classes etc. with WPF?

  5. It seems that only the RequiredAttribute is validated when Validator.TryValidateObject(entity, vc, validationResults) is called.

    To validate all properties call Validator.TryValidateObject(entity, vc, validationResults, TRUE)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s