0

Je suis très nouveau à EF4. J'ai posté quelques fois je pense en ce qui concerne l'héritage, la validation mais mon objectif global est de réduire autant que possible la quantité de code que j'écris. Je ne m'intéresse pas (encore) aux POCOs, aux masses de bidouillage ObjectContext: je veux profiter du EF et du minimum de codage. Donc, l'épineux problème de la validation. Jetez un oeil à cet exemple simplifié et (à part les alias DRY Buddies et usages douteux), cela ressemble-t-il à une approche à moitié décente?Valider cette approche de validation EF4?

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

Il y a quelque chose de plutôt cool à ce sujet. Je peux appeler ce qui précède comme ceci:

var validationResults = person.Validate(); 

MAIS, si je veux juste quelques vérifications de base, je peux dépouiller Valider(), la substance [de SelfValidation], conserver les attributs et il suffit d'appeler:

var validationResults = Validation.Validate(person); 

J'ai juste besoin d'inclure autant de validation que nécessaire et il y a une configuration ZERO dans web.config.

Comment est la coupe de mon foc? :)

Richard

+0

personnellement, je ne pense pas que vous devriez valider dans votre modèle pour des choses comme "longueur du nom de famille". C'est la validation de * input *, ce qui devrait être fait dans le niveau présentation. La validation de dernière minute devrait être faite par EF lui-même qui validera les champs par rapport aux contraintes de base de données sous-jacentes (par exemple 'NVARCHAR (4)' - qui empêche tout caractère> 4 caractères). À quel moment de votre application appelez-vous 'person.Validate'? – RPM1984

+0

Comme je l'ai dit, un exemple simple. Imaginez-le dans le contexte d'une application du monde réel avec validation du monde réel qui prendrait trop de temps à coder par exemple. – Richard

+0

Je suppose (encore simplement!) Appeler comme: using (var contexte = nouveau ModelContainer()) {var personne = new Personne(); var validationResults = Validation.Validate (personne); if (validationResults.IsValid) {context.AddToPeople (personne); } else {WriteValidationResults (validationResults); }} mais ce truc EF est encore nouveau pour moi, alors ... – Richard

Répondre

1

Je suis personnellement pas fan d'appeler la validation directement dans le code, et surtout pas directement sur une entité elle-même. Il y aura beaucoup d'endroits où vous appellerez Validate et il est facile d'oublier d'appeler Validate. Au lieu de cela, laissez le ObjectContext invoquer le cadre de validation sous-jacent automatiquement pour TOUTES les entités qui ont changé, et lancer une exception spéciale (qui peut être interceptée dans la couche de présentation) lorsque des erreurs de validation se produisent.

Vous pouvez le faire en accrochant sur l'événement ObjectContext.SavingChanges et déclencher la validation là. Vous pouvez écrire votre ObjectContext partielle comme suit:

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

Vous pouvez en lire davantage here.

+0

Je sais que c'est un peu vieux. Mais c'est une très belle approche +1 –