2009-09-19 4 views
2

En travaillant à travers le NerdDinner Tutorial, j'essaie de trouver un bon moyen d'effectuer une validation sur les propriétés qui ne dépend pas d'une classe partielle générée par LINQ-to-SQL . Voici quelques exemples de code de ce que je l'ai fait jusqu'à présent:LINQ to SQL: OnValidate() et les classes de modèle de domaine personnalisé

public abstract class DomainEntity 
{ 
    public IEnumerable<ValidationError> ValidationErrors { get; private set; } 

    public bool Validate() 
    { 
     bool isValid = false; 

     if (this.ValidationErrors != null) 
      this.ValidationErrors = null; 

     this.ValidationErrors = this.GetValidationErrors(); 

     if (this.ValidationErrors.Count() == 0) 
      isValid = true; 

     return isValid; 
    } 

    protected abstract IEnumerable<ValidationError> GetValidationErrors(); 
} 

public partial class Email : DomainEntity 
{ 
    protected override IEnumerable<ValidationError> GetValidationErrors() 
    { 
     if (!this.ValidateAddress()) 
      yield return new ValidationError("Address", DomainResources.EmailAddressValidationErrorMessage); 

     yield break; 
    } 

    partial void OnValidate(ChangeAction action) 
    { 
     bool isValid = this.Validate(); 

     if (!isValid) 
      throw new InvalidEmailException(this); 
    } 

    private bool ValidateAddress() 
    { 
     // TODO: Use a regex to validate the email address. 

     return !string.IsNullOrEmpty(this.Address); 
    } 
} 

Où Email est un type généré LINQ à SQL basé sur une table Email. Comme la table Email n'est qu'une des nombreuses entités liées à une classe de modèle de domaine (par exemple, "User"), l'idéal est de créer une classe de modèle de domaine "User" et d'utiliser les attributs Validation Application Block pour valider les propriétés. En d'autres termes, je voudrais utiliser ceci:

public class User 
{ 
    private Email emailEntity; 

    [EmailAddressValidator] 
    public string EmailAddress 
    { 
     get { return emailEntity.Address; } 
     set { emailEntity.Address = value; } 
    } 
} 

Alors que si je change mon schéma de base de données, et les changements passent à travers mes classes LINQ to SQL généré, je ne les avez pas partiel rendus orphelins classes (comme la classe partielle Email). Je veux également profiter de l'intégration des attributs Validation Application Block, de sorte que je n'ai pas besoin de gérer une collection de regex, comme cela est fait dans le tutoriel NerdDinner. De plus, l'utilisateur en tant que classe de domaine va être l'unité fonctionnelle du domaine, pas le courrier électronique ni les autres entités, pour créer des modèles de vue, afficher des vues, etc .. Cependant, il est impossible de capturer l'appel de validation:

public abstract class DomainEntity 
{ 
    public event EventHandler Validation(object sender, EventArgs args); 
    protected void OnValidation() 
    { 
     if (this.Validate != null) 
      this.Validate(this, EventArgs.Empty); 
    } 
} 

public partial class Email 
{ 
    partial void OnValidate(ChangeAction action) 
    { 
     this.OnValidation(); 
    } 
} 

Ensuite, l'utilisateur doit se connecter à cet événement et gérer toutes les validations dans l'utilisateur. Cela fonctionnerait-il même avec le bloc d'application de validation? Comment effectuer une validation dans les classes de domaine agrégées comme utilisateur d'une manière sensible?

+0

REMARQUE: J'ai une table de type "User" dans la base de données, mais je parle d'un utilisateur de classe LINQ-to-SQL indépendant qui tirera de différentes tables. Si je change le schéma (le dénormaliser), l'objectif est de mettre à jour uniquement la classe User pour refléter la modification sous-jacente dans les entités générées. – emptyset

Répondre

1

Traiter la validation comme un service plutôt que comme une responsabilité de l'entité, cela vous permettra de séparer l'implémentation de la validation de la définition de ce qui est valide et de transformer la validation en une opération explicite plutôt qu'implicite (géré par L2S).

Jetez un oeil à la validation courante pour .net (http://www.codeplex.com/FluentValidation) pour une bonne implémentation de cette approche.

+0

On dirait que ça pourrait bien marcher - je vais essayer de jouer avec ça ce week-end. – emptyset

0

Regardez l'article this. Il explique comment valider LINQ to SQL à l'aide du bloc d'application de validation Microsoft.

Comme l'explique l'article, l'utilisation du bloc d'application de validation consiste à utiliser la validation basée sur la configuration au lieu de la validation basée sur l'attribut. Parce que les entités sont générées, l'utilisation de l'approche basée sur les attributs est presque impossible.