216 votes

DbEntityValidationException - Comment puis-je facilement savoir ce qui a provoqué l'erreur ?

J'ai un projet qui utilise Entity Framework. En appelant SaveChanges sur mon DbContext j'obtiens l'exception suivante :

System.Data.Entity.Validation.DbEntityValidationException : La validation a échoué pour une ou plusieurs entités. Voir la propriété 'EntityValidationErrors' pour plus de détails. pour plus de détails.

Tout cela est très bien, mais je ne veux pas attacher un débogueur à chaque fois que cette exception se produit. De plus, dans les environnements de production, je ne peux pas facilement attacher un débogueur et je dois donc me donner beaucoup de mal pour reproduire ces erreurs.

Comment puis-je voir les détails cachés dans le DbEntityValidationException ?

427voto

Martin Devillers Points 3539

La solution la plus simple est de remplacer SaveChanges sur la classe de vos entités. Vous pouvez attraper le DbEntityValidationException de déballer les erreurs réelles et de créer une nouvelle DbEntityValidationException avec le message amélioré.

  1. Créez une classe partielle à côté de votre fichier SomethingSomething.Context.cs.
  2. Utilisez le code au bas de cet article.
  3. C'est tout. Votre implémentation utilisera automatiquement le SaveChanges surchargé sans aucun travail de refactoring.

Votre message d'exception ressemblera maintenant à ceci :

System.Data.Entity.Validation.DbEntityValidationException : La validation a échoué pour une ou plusieurs entités. Voir la propriété 'EntityValidationErrors'. pour plus de détails. Les erreurs de validation sont les suivantes : Le champ PhoneNumber doit être une chaîne ou un tableau d'une longueur maximale de '12'. LastName est obligatoire.

Vous pouvez déposer la surcharge SaveChanges dans n'importe quelle classe qui hérite de DbContext :

public partial class SomethingSomethingEntities
{
    public override int SaveChanges()
    {
        try
        {
            return base.SaveChanges();
        }
        catch (DbEntityValidationException ex)
        {
            // Retrieve the error messages as a list of strings.
            var errorMessages = ex.EntityValidationErrors
                    .SelectMany(x => x.ValidationErrors)
                    .Select(x => x.ErrorMessage);
    
            // Join the list to a single string.
            var fullErrorMessage = string.Join("; ", errorMessages);
    
            // Combine the original exception message with the new one.
            var exceptionMessage = string.Concat(ex.Message, " The validation errors are: ", fullErrorMessage);
    
            // Throw a new DbEntityValidationException with the improved exception message.
            throw new DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors);
        }
    }
}

El DbEntityValidationException contient également les entités qui ont causé les erreurs de validation. Ainsi, si vous avez besoin d'encore plus d'informations, vous pouvez modifier le code ci-dessus pour obtenir des informations sur ces entités.

Voir aussi : http://devillers.nl/improving-dbentityvalidationexception/

47voto

Eric Hirst Points 156

Comme Martin l'a indiqué, il y a plus d'informations dans la DbEntityValidationResult . J'ai trouvé utile d'obtenir à la fois le nom de la classe et le nom de la propriété de mon POCO dans chaque message, et je voulais éviter d'avoir à écrire des messages personnalisés. ErrorMessage sur tous mes [Required] tags juste pour ça.

La modification suivante du code de Martin a permis de régler ces détails pour moi :

// Retrieve the error messages as a list of strings.
List<string> errorMessages = new List<string>();
foreach (DbEntityValidationResult validationResult in ex.EntityValidationErrors)
{
    string entityName = validationResult.Entry.Entity.GetType().Name;
    foreach (DbValidationError error in validationResult.ValidationErrors)
    {
        errorMessages.Add(entityName + "." + error.PropertyName + ": " + error.ErrorMessage);
    }
}

0voto

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X