0

我对 EF4很陌生。我已经发布了几次关于继承、验证的想法,但我的总体目标是尽可能减少我编写的代码量。我(还)对 POCO 不感兴趣,大量的 ObjectContext 摆弄:我想要 EF 的好处和最少的编码。

所以,验证的棘手问题。看看这个简化的例子(除了 DRY Buddies 和狡猾的 usings 别名),这看起来像一个半体面的方法吗?

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; }
    }
}

这有点酷。我可以这样称呼上面的:

var validationResults = person.Validate();

但是,如果我只是想要一些基本的检查,我可以去掉 Validate(),[SelfValidation] 的东西,保留属性,然后调用:

var validationResults = Validation.Validate(person);

我只需要包含我需要的尽可能多的验证,并且 web.config 中有零配置。

我的吊臂剪得怎么样了?:)

理查德

4

1 回答 1

1

我个人不喜欢直接在代码中调用验证,尤其是不直接在实体本身上调用验证。会有很多地方你会打电话Validate,很容易忘记打电话Validate。相反,让ObjectContext所有已更改的实体自动调用底层验证框架,并在发生验证错误时抛出一个特殊异常(可以在表示层中捕获)。

您可以通过挂钩ObjectContext.SavingChanges事件并在那里触发验证来做到这一点。您可以ObjectContext按如下方式编写部分内容:

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);
    }    
} 

你可以在这里阅读更多关于它的信息。

于 2010-12-11T23:06:53.417 回答