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. In this blog, I present a quick and easy way to unwrap and rethrow these exceptions with a more meaningful message.
Developers who have used Entity Framework are probably familiar with the following message:
System.Data.Entity.Validation.DbEntityValidationException: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
This message is quite clear in its intent: Something isn’t valid and if you want to find out what that is then you should attach a debugger and inspect the exception. While this is certainly a valid approach, attaching debuggers isn’t always practical (e.g. production environments). Moreover, being the lazy developer I am, I don’t want to attach a debugger to find out what field caused the error: I want the exception message to tell me in the first place!
DbEntityValidationException
is thrown by the SaveChanges
method which resides on the DbContext
class. Fortunately, you can override the default behavior of SaveChanges
. Assuming you use a database-first approach, your Visual Studio solution should contain a bunch of files like these:
- Northwind.cs
- Northwind.Context.cs
- Northwind.Context.tt
- Northwind.Designer.cs
- Northwind.edmx
- Northwind.edmx.diagram
- Northwind.tt
Northwind.Context.cs is the file of interest here. This file is automatically generated by Northwind.Context.tt. It describes the class you use in code to perform operations on the database. This class inherits from DbContext
, which in turn contains SaveChanges
, the method responsible for throwing the DbEntityValidationException
. This method is virtual and can thus be overridden. However, changing Northwind.Context.cs is not recommended since the tt-file will overwrite this file on any change to the EDMX. Luckily, the class itself is partial, which means you can add your own class to the solution.
- First, create a new partial class in the same location as where your EDMX resides. In my example, I called the file NorthwindEntities.cs, which is also the name of the class.
- Second, use the following piece of C# code to override the
SaveChanges
implementation.
public partial class NorthwindEntities { 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); } } }
That’s it! The rest of your code will automatically use the overridden SaveChanges
so you don’t have to change anything else. From now on, your exceptions will 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.
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.
I hope this blog saves you time debugging, so you can spend more time writing awesome code instead! 🙂
This article is also featured on StackOverflow and My Personal Blog!
20 comments
This is incredibly useful and is making working threw Validation exceptions a LOT more straight forward.
Thanks.
VipX1 Dev.
Great, thanks a lot.
TheDutchGuy
What if I want those Details to reach the client?
I have EF context exposed through a WCF Data Service and I still get the formal ( no-details) DataServiceRequestException “An error occurred while processing this request”. What to do?
Razvan
This helped me out so much with a frustrating issue, thanks!
Alex
Thanks
useful 🙂
sameer
Thank mate. That was awsome.
Marian Pintilie
Nice one Martin
I’d been doing this every time I called Context.SaveChanges(), this makes it so simple.
Thanks again.
Mark Harby
I’ll just say that, thank you very much for bring me this information. I usually don´t leave replies but now you give me an excellent tool for my project.
Thank you again, I’m gonna put this webpage as the link for copyright into my code.
Regards.
Rodrigo Uzcátegui
Excellent..
Thanks very much for this blog.. very very helpful.
It saved me hell lot of time.
Regards
Shafeeq
[…] entities. See ‘EntityValidationErrors’ property for more details” and found a blog post to follow which provided me the details I needed when debugging to solve the […]
Template, Registration and Login | Devin W.C. Ryan
Below is a version that includes all the necessary includes:
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.Linq;
namespace MyNamespace
{
public partial class MyContext : DbContext
{
// Override base SaveChanges to expand out validation errors so client gets an actually helpful message
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);
}
}
}
}
</pre
Sean
Mastch… Liked it.. Thanx…
TK
What if I am making use of code first?
Sunny Okoro
It works the same way!
asdf
Thanks so much !
for almost a week I have been through that error.
Mohamed Moka
thanks a lot .. it is perfectly useful
bharathiraja
[…] Looking on google I found this post: https://blogs.infosupport.com/improving-dbentityvalidationexception/ […]
Entity Framework System.Data.Entity.Validation.DbEntityValidationException: Validation failed for one or more entities. See ‘EntityValidationErrors’ property for more details | Un programmatore tra i cordoli
very useful i found the solution . now i’m very happy..
Sathish
Awesome!
LB
thanks
anonymous