0

Ich bin sehr neu zu EF4. Ich habe ein paar Mal gepostet, was die Vererbung betrifft, aber mein Hauptziel ist es, die Menge an Code, die ich schreibe, so weit wie möglich zu reduzieren. Ich bin (noch) nicht an POCOs, Massen von ObjectContext-Fiedeln interessiert: Ich möchte den Nutzen von EF und ein Minimum an Kodierung.Diesen EF4-Validierungsansatz validieren?

Also, das heikle Thema der Validierung. Sehen Sie sich dieses vereinfachte Beispiel an und (abgesehen von DRY Buddies und dubiosen Using-Aliasen), sieht das wie ein halbwegs anständiger Ansatz aus?

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

Da ist etwas ziemlich cooles. Ich kann das wie dies oben nennen:

var validationResults = person.Validate(); 

ABER, wenn ich will nur einige grundlegende Überprüfung, ich kann Validate Streifen aus(), die [SelfValidation] Sachen, die Attribute halten und dann rufen Sie einfach:

var validationResults = Validation.Validate(person); 

Ich muss nur so viel Validierung wie ich brauche und es gibt ZERO-Konfiguration in web.config.

Wie ist der Schnitt meines Jib? :)

Richard

+0

persönlich, ich glaube nicht, dass Sie in Ihrem Modell für Dinge wie "Länge des Nachnamens" validieren sollten. Das ist die Validierung von * input *, die in der Präsentationsschicht vorgenommen werden sollte. Last-Minute-Validierung sollte von EF selbst durchgeführt werden, die die Felder gegen die zugrunde liegenden Datenbank Einschränkungen (z. B. NVARCHAR (4) '- was alles> 4 Zeichen verhindert). An welcher Stelle in Ihrer Bewerbung würden Sie 'person.Validate' nennen? – RPM1984

+0

Wie gesagt, ein einfaches Beispiel. Stellen Sie es sich im Kontext einer echten Welt-App mit einer Validierung der realen Welt vor, die zu lange dauern würde, um als Beispiel zu codieren. – Richard

+0

Ich denke (wieder einfach!) Rufe wie folgt auf: using (var context = new ModelContainer()) {var person = new Person(); var validationResults = Validation.Validate (Person); if (validationResults.IsValid) {context.AddToPeople (Person); } else {WriteValidationResults (validationResults); }} aber dieses EF-Zeug ist für mich immer noch neu, also ... – Richard

Antwort

1

Ich persönlich bin kein Fan von Validierung direkt im Code aufrufen, und schon gar nicht direkt auf eine Entität selbst. Es wird viele Orte geben, wo Sie anrufen werden Validate und es ist leicht zu vergessen, Validate zu rufen. Lassen Sie stattdessen das ObjectContext das zugrunde liegende Validierungsframework für ALLE Entitäten, die geändert wurden, automatisch aufrufen und eine spezielle Ausnahme auslösen (die in der Präsentationsschicht gefangen werden kann), wenn Validierungsfehler auftreten.

Sie können dies tun, indem Sie auf das Ereignis ObjectContext.SavingChanges einhaken und dort die Validierung auslösen.

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

Sie können mehr darüber lesen here: Sie können Ihre Teil ObjectContext wie folgt schreiben.

+0

Ich weiß, es ist ein bisschen alt. Aber das ist ein sehr netter Ansatz +1 –