DbEntityValidationException is the exception thrown by Entity Framework when entity validation fails. While this exception is extremely valuable, the exception message omits the most important bit of information: The actual validation errors.
The easiest solution is to override SaveChanges
on your entities class. You can catch the DbEntityValidationException
, unwrap the actual errors and create a new DbEntityValidationException
with the improved message.
Your exception message will now look like this:
System.Data.Entity.Validation.DbEntityValidationException: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details. The validation errors are: The field PhoneNumber must be a string or array type with a maximum length of '12'; The LastName field is required.
You can drop the overridden SaveChanges in any class that inherits from 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);
}
}
}
The DbEntityValidationException
also contains the entities that caused the validation errors. So if you require even more information, you can change the above code to output information about these entities.
See also: http://devillers.nl/improving-dbentityvalidationexception/
As Martin indicated, there is more information in the DbEntityValidationResult
. I found it useful to get both my POCO class name and property name in each message, and wanted to avoid having to write custom ErrorMessage
attributes on all my [Required]
tags just for this.
The following tweak to Martin's code took care of these details for me:
// 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);
}
}
To view the EntityValidationErrors
collection, add the following Watch expression to the Watch window.
((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors
I'm using visual studio 2013
While you are in debug mode within the catch {...}
block open up the "QuickWatch" window (ctrl+alt+q) and paste in there:
((System.Data.Entity.Validation.DbEntityValidationException)ex).EntityValidationErrors
This will allow you to drill down into the ValidationErrors
tree. It's the easiest way I've found to get instant insight into these errors.
For Visual 2012+ users who care only about the first error and might not have a catch
block, you can even do:
((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors.First().ValidationErrors.First().ErrorMessage
To quickly find a meaningful error message by inspecting the error during debugging:
Add a quick watch for:
((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors
Drill down into EntityValidationErrors like this:
(collection item e.g. [0]) > ValidationErrors > (collection item e.g. [0]) > ErrorMessage
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With