C# 验证这个EF4验证方法?

C# 验证这个EF4验证方法?,c#,validation,entity-framework-4,enterprise-library,validation-application-bl,C#,Validation,Entity Framework 4,Enterprise Library,Validation Application Bl,我对EF4很陌生。我已经发布了几次关于继承、验证的帖子,但我的总体目标是尽可能减少我编写的代码量。我对POCOs(大量的ObjectContext篡改)不感兴趣:我想要EF的好处和最少的编码 因此,验证是一个棘手的问题。看看这个简化的例子(除了干巴巴的朋友和使用别名的诡计多端之外),这看起来像是一个半体面的方法吗 namespace Model { using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;

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

因此,验证是一个棘手的问题。看看这个简化的例子(除了干巴巴的朋友和使用别名的诡计多端之外),这看起来像是一个半体面的方法吗

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中没有配置

我的三角帆剪得怎么样?:)


Richard

我个人不喜欢直接在代码中调用验证,尤其是不直接在实体本身上调用验证。如果您要调用
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);
    }    
} 
公共部分类ModelContainer
{
部分无效OnContextCreated()
{
这就是储蓄的变化+=
(sender,e)=>Validate(this.GetChangedEntities());
}
私有IEnumerable GetChangedEntities()
{
常量实体状态添加和修改=
EntityState.Added | EntityState.Modified;
var entries=this.ObjectStateManager
.GetObjectStateEntries(添加和修改);
返回条目。其中(e=>e!=null);
}
私有静态void验证(IEnumerable实体)
{
ValidationResults[]invalidResults=(
从实体到实体
let type=entity.GetType()
让validator=ValidationFactory.CreateValidator(类型)
让结果=validator.Validate(实体)
where!results.IsValid
选择结果);
如果(无效结果长度>0)
抛出新的ValidationException(invalidResults);
}    
} 

您可以阅读更多信息。

就个人而言,我认为您不应该在模型中验证诸如“姓氏长度”之类的内容。这就是输入的验证,应该在表示层中完成。最后一分钟的验证应由EF自己完成,EF将根据基础数据库约束验证字段(例如
NVARCHAR(4)
-防止任何超过4个字符的内容)。在应用程序中的什么时候调用
person.Validate
?正如我所说,这是一个简单的示例。想象一下,在一个具有真实世界验证的真实世界应用程序的上下文中,编写一个示例可能需要很长时间。我猜(同样简单!)调用如下:使用(var context=newmodelcontainer()){var person=new person();var validationResults=validation.Validate(person);if(validationResults.isvalidate){context.AddToPeople(person);}else{WriteValidationResults(validationResults);}}但是EF的东西对我来说还是新的,所以…CTP5内置了DataAnnotations验证。你能等一下吗?我最近注意到CTP5内置了对DataAnnotation的支持,但似乎只有在这一点上才支持代码?我先要模型/数据库。典型:)现在,我将使用下面的答案,我保证在6个月左右的时间内重构它会很愉快。我知道它有点旧。但这是一个非常好的方法+1