简体   繁体   中英

Validate This EF4 Validation Approach?

I'm very new to EF4. I've posted a couple of times I think regarding inheritance, validation but my overall aim is to reduce the amount of code I write as much as possible. I'm not interested (yet) in POCOs, masses of ObjectContext fiddling: I want the benefit of EF and minimum of coding.

So, the thorny issue of validation. Take a look at this simplified example and (aside from DRY Buddies and dodgy usings aliases), is this looking like a half-decent approach?

namespace Model
{
    using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;
    using DataAnnotations = System.ComponentModel.DataAnnotations;
    using Validation = Microsoft.Practices.EnterpriseLibrary.Validation;

    [HasSelfValidation]
    [DataAnnotations.MetadataType(typeof(PersonValidator))]
    public partial class Person
    {
        [SelfValidation]
        public Validation.ValidationResults Validate()
        {
            var validationResults = Validation.Validation.Validate(this);

            if (string.IsNullOrEmpty(this.LastName) || this.LastName.Length > 4)
            {
                validationResults.AddResult(new Validation.ValidationResult("This is a test error message for a custom validation error.", this, null, null, null));
            }

            return validationResults;
        }
    }

    [HasSelfValidation]
    public class PersonValidator
    {
        [NotNullValidator(MessageTemplate = "First Name must be supplied.")]
        [ContainsCharactersValidator("Rcd", ContainsCharacters.All, MessageTemplate = "{1} must contains characters \"{3}\" ({4}).")]
        [StringLengthValidator(5, 50, MessageTemplate = "{1} (\"{0}\") must be between {3} ({4}) and {5} ({6}) characters in length.")]
        public string FirstName { get; set; }

        [NotNullValidator(MessageTemplate = "Last Name must be supplied.")]
        [ContainsCharactersValidator("Wes", ContainsCharacters.All, MessageTemplate = "{1} must contains characters \"{3}\" ({4}).")]
        [StringLengthValidator(5, 50, MessageTemplate = "{1} (\"{0}\") must be between {3} ({4}) and {5} ({6}) characters in length.")]
        public string LastName { get; set; }
    }
}

There's something rather cool about this. I can call the above like this:

var validationResults = person.Validate();

BUT, if I just want some basic checking, I can strip out Validate(), the [SelfValidation] stuff, keep the attributes and then just call:

var validationResults = Validation.Validate(person);

I only need to include as much validation as I need and there's ZERO configuration in web.config.

How's the cut of my jib? :)

Richard

I'm personally not a fan of calling validation directly in code, and especially not directly on a entity itself. There will be a lot of places were you will call Validate and it is easy to forget to call Validate . Instead, let the ObjectContext invoke the underlying validation framework automatically for ALL entities that have changed, and throw a special exception (that can be caught in the presentation layer) when validation errors occur.

You can do this by hooking onto the ObjectContext.SavingChanges event and trigger validation there. You can write your partial ObjectContext as follows:

public partial class ModelContainer
{
    partial void OnContextCreated()
    {
        this.SavingChanges +=
            (sender, e) => Validate(this.GetChangedEntities());
    }

    private IEnumerable<object> GetChangedEntities()
    {
        const EntityState AddedAndModified =
            EntityState.Added | EntityState.Modified;

        var entries = this.ObjectStateManager
            .GetObjectStateEntries(AddedAndModified);

        return entries.Where(e => e != null);
    }

    private static void Validate(IEnumerable<object> entities)
    {
        ValidationResults[] invalidResults = (
            from entity in entities
            let type = entity.GetType()
            let validator = ValidationFactory.CreateValidator(type)
            let results = validator.Validate(entity)
            where !results.IsValid
            select results).ToArray();

        if (invalidResults.Length > 0)
            throw new ValidationException(invalidResults);
    }    
} 

You can read more about it here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM