874

I am having this error when seeding my database with code first approach.

Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.

To be honest I don't know how to check the content of the validation errors. Visual Studio shows me that it's an array with 8 objects, so 8 validation errors.

This was working with my previous model, but I made a few changes that I explain below:

  • I had an enum called Status, I changed it to a class called Status
  • I changed the class ApplicantsPositionHistory to have 2 foreign key to the same table

Excuse me for the long code, but I have to paste it all. The exception is thrown in the last line of the following code.

namespace Data.Model
{  
    public class Position
    {
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]   
        public int PositionID { get; set; }

        [Required(ErrorMessage = "Position name is required.")]
        [StringLength(20, MinimumLength = 3, ErrorMessage = "Name should not be longer than 20 characters.")]
        [Display(Name = "Position name")]              
        public string name { get; set; }

        [Required(ErrorMessage = "Number of years is required")] 
        [Display(Name = "Number of years")]        
        public int yearsExperienceRequired { get; set; }

        public virtual ICollection<ApplicantPosition> applicantPosition { get; set; }
    }

    public class Applicant
    {
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]      
        public int ApplicantID { get; set; }

        [Required(ErrorMessage = "Name is required")] 
        [StringLength(20, MinimumLength = 3, ErrorMessage="Name should not be longer than 20 characters.")]
        [Display(Name = "First and LastName")]
        public string name { get; set; }

        [Required(ErrorMessage = "Telephone number is required")] 
        [StringLength(10, MinimumLength = 3, ErrorMessage = "Telephone should not be longer than 20 characters.")]
        [Display(Name = "Telephone Number")]
        public string telephone { get; set; }

        [Required(ErrorMessage = "Skype username is required")] 
        [StringLength(10, MinimumLength = 3, ErrorMessage = "Skype user should not be longer than 20 characters.")]
        [Display(Name = "Skype Username")]
        public string skypeuser { get; set; }

        public byte[] photo { get; set; }

        public virtual ICollection<ApplicantPosition> applicantPosition { get; set; }
    }

    public class ApplicantPosition
    {
        [Key]
        [Column("ApplicantID", Order = 0)]
        public int ApplicantID { get; set; }

        [Key]
        [Column("PositionID", Order = 1)]
        public int PositionID { get; set; }

        public virtual Position Position { get; set; }

        public virtual Applicant Applicant { get; set; }

        [Required(ErrorMessage = "Applied date is required")] 
        [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
        [Display(Name = "Date applied")]     
        public DateTime appliedDate { get; set; }

        [Column("StatusID", Order = 0)]
        public int StatusID { get; set; }

        public Status CurrentStatus { get; set; }

        //[NotMapped]
        //public int numberOfApplicantsApplied
        //{
        //    get
        //    {
        //        int query =
        //             (from ap in Position
        //              where ap.Status == (int)Status.Applied
        //              select ap
        //                  ).Count();
        //        return query;
        //    }
        //}
    }

    public class Address
    {
        [StringLength(20, MinimumLength = 3, ErrorMessage = "Country should not be longer than 20 characters.")]
        public string Country { get; set; }

        [StringLength(20, MinimumLength = 3, ErrorMessage = "City  should not be longer than 20 characters.")]
        public string City { get; set; }

        [StringLength(50, MinimumLength = 3, ErrorMessage = "Address  should not be longer than 50 characters.")]
        [Display(Name = "Address Line 1")]     
        public string AddressLine1 { get; set; }

        [Display(Name = "Address Line 2")]
        public string AddressLine2 { get; set; }   
    }

    public class ApplicationPositionHistory
    {
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]
        public int ApplicationPositionHistoryID { get; set; }

        public ApplicantPosition applicantPosition { get; set; }

        [Column("oldStatusID")]
        public int oldStatusID { get; set; }

        [Column("newStatusID")]
        public int newStatusID { get; set; }

        public Status oldStatus { get; set; }

        public Status newStatus { get; set; }

        [StringLength(500, MinimumLength = 3, ErrorMessage = "Comments  should not be longer than 500 characters.")]
        [Display(Name = "Comments")]
        public string comments { get; set; }

        [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
        [Display(Name = "Date")]     
        public DateTime dateModified { get; set; }
    }

    public class Status
    {
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]
        public int StatusID { get; set; }

        [StringLength(20, MinimumLength = 3, ErrorMessage = "Status  should not be longer than 20 characters.")]
        [Display(Name = "Status")]
        public string status { get; set; }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.IO;

namespace Data.Model
{
    public class HRContextInitializer : DropCreateDatabaseAlways<HRContext>
    {
        protected override void Seed(HRContext context)
        {
            #region Status
            Status applied = new Status() { status = "Applied" };
            Status reviewedByHR = new Status() { status = "Reviewed By HR" };
            Status approvedByHR = new Status() { status = "Approved by HR" };
            Status rejectedByHR = new Status() { status = "Rejected by HR" };
            Status assignedToTechnicalDepartment = new Status() { status = "Assigned to Technical Department" };
            Status approvedByTechnicalDepartment = new Status() { status = "Approved by Technical Department" };
            Status rejectedByTechnicalDepartment = new Status() { status = "Rejected by Technical Department" };

            Status assignedToGeneralManager = new Status() { status = "Assigned to General Manager" };
            Status approvedByGeneralManager = new Status() { status = "Approved by General Manager" };
            Status rejectedByGeneralManager = new Status() { status = "Rejected by General Manager" };

            context.Status.Add(applied);
            context.Status.Add(reviewedByHR);
            context.Status.Add(approvedByHR);
            context.Status.Add(rejectedByHR);
            context.Status.Add(assignedToTechnicalDepartment);
            context.Status.Add(approvedByTechnicalDepartment);
            context.Status.Add(rejectedByTechnicalDepartment);
            context.Status.Add(assignedToGeneralManager);
            context.Status.Add(approvedByGeneralManager);
            context.Status.Add(rejectedByGeneralManager); 
            #endregion    

            #region Position
            Position netdeveloper = new Position() { name = ".net developer", yearsExperienceRequired = 5 };
            Position javadeveloper = new Position() { name = "java developer", yearsExperienceRequired = 5 };
            context.Positions.Add(netdeveloper);
            context.Positions.Add(javadeveloper); 
            #endregion

            #region Applicants
            Applicant luis = new Applicant()
            {
                name = "Luis",
                skypeuser = "le.valencia",
                telephone = "0491732825",
                photo = File.ReadAllBytes(@"C:\Users\LUIS.SIMBIOS\Documents\Visual Studio 2010\Projects\SlnHR\HRRazorForms\Content\pictures\1.jpg")
            };

            Applicant john = new Applicant()
            {
                name = "John",
                skypeuser = "jo.valencia",
                telephone = "3435343543",
                photo = File.ReadAllBytes(@"C:\Users\LUIS.SIMBIOS\Documents\Visual Studio 2010\Projects\SlnHR\HRRazorForms\Content\pictures\2.jpg")
            };

            context.Applicants.Add(luis);
            context.Applicants.Add(john); 
            #endregion

            #region ApplicantsPositions
            ApplicantPosition appicantposition = new ApplicantPosition()
            {
                Applicant = luis,
                Position = netdeveloper,
                appliedDate = DateTime.Today,
                StatusID = 1
            };

            ApplicantPosition appicantposition2 = new ApplicantPosition()
            {
                Applicant = john,
                Position = javadeveloper,
                appliedDate = DateTime.Today,
                StatusID = 1
            };        

            context.ApplicantsPositions.Add(appicantposition);            
            context.ApplicantsPositions.Add(appicantposition2); 
            #endregion

            context.SaveChanges(); --->> Error here
        }
    }
}
Laurel
  • 5,965
  • 14
  • 31
  • 57
Luis Valencia
  • 32,619
  • 93
  • 286
  • 506

29 Answers29

1346

To be honest I don't know how to check the content of the validation errors. Visual Studio shows me that it's an array with 8 objects, so 8 validation errors.

Actually you should see the errors if you drill into that array in Visual studio during debug. But you can also catch the exception and then write out the errors to some logging store or the console:

try
{
    // Your code...
    // Could also be before try if you know the exception occurs in SaveChanges

    context.SaveChanges();
}
catch (DbEntityValidationException e)
{
    foreach (var eve in e.EntityValidationErrors)
    {
        Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
            eve.Entry.Entity.GetType().Name, eve.Entry.State);
        foreach (var ve in eve.ValidationErrors)
        {
            Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
                ve.PropertyName, ve.ErrorMessage);
        }
    }
    throw;
}

EntityValidationErrors is a collection which represents the entities which couldn't be validated successfully, and the inner collection ValidationErrors per entity is a list of errors on property level.

These validation messages are usually helpful enough to find the source of the problem.

Edit

A few slight improvements:

The value of the offending property can be included in the inner loop like so:

        foreach (var ve in eve.ValidationErrors)
        {
            Console.WriteLine("- Property: \"{0}\", Value: \"{1}\", Error: \"{2}\"",
                ve.PropertyName,
                eve.Entry.CurrentValues.GetValue<object>(ve.PropertyName),
                ve.ErrorMessage);
        }

While debugging Debug.Write might be preferable over Console.WriteLine as it works in all kind of applications, not only console applications (thanks to @Bart for his note in the comments below).

For web applications that are in production and that use Elmah for exception logging it turned out to be very useful for me to create a custom exception and overwrite SaveChanges in order to throw this new exception.

The custom exception type looks like this:

public class FormattedDbEntityValidationException : Exception
{
    public FormattedDbEntityValidationException(DbEntityValidationException innerException) :
        base(null, innerException)
    {
    }

    public override string Message
    {
        get
        {
            var innerException = InnerException as DbEntityValidationException;
            if (innerException != null)
            {
                StringBuilder sb = new StringBuilder();

                sb.AppendLine();
                sb.AppendLine();
                foreach (var eve in innerException.EntityValidationErrors)
                {
                    sb.AppendLine(string.Format("- Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                        eve.Entry.Entity.GetType().FullName, eve.Entry.State));
                    foreach (var ve in eve.ValidationErrors)
                    {
                        sb.AppendLine(string.Format("-- Property: \"{0}\", Value: \"{1}\", Error: \"{2}\"",
                            ve.PropertyName,
                            eve.Entry.CurrentValues.GetValue<object>(ve.PropertyName),
                            ve.ErrorMessage));
                    }
                }
                sb.AppendLine();

                return sb.ToString();
            }

            return base.Message;
        }
    }
}

And SaveChanges can be overwritten the following way:

public class MyContext : DbContext
{
    // ...

    public override int SaveChanges()
    {
        try
        {
            return base.SaveChanges();
        }
        catch (DbEntityValidationException e)
        {
            var newException = new FormattedDbEntityValidationException(e);
            throw newException;
        }
    }
}

A few remarks:

  • The yellow error screen that Elmah shows in the web interface or in the sent emails (if you have configured that) now displays the validation details directly at the top of the message.

  • Overwriting the Message property in the custom exception instead of overwriting ToString() has the benefit that the standard ASP.NET "Yellow screen of death (YSOD)" displays this message as well. In contrast to Elmah the YSOD apparently doesn't use ToString(), but both display the Message property.

  • Wrapping the original DbEntityValidationException as inner exception ensures that the original stack trace will still be available and is displayed in Elmah and the YSOD.

  • By setting a breakpoint on the line throw newException; you can simply inspect the newException.Message property as a text instead of drilling into the validation collections which is a bit awkward and doesn't seem to work easily for everyone (see comments below).

Laurel
  • 5,965
  • 14
  • 31
  • 57
Slauma
  • 175,098
  • 59
  • 401
  • 420
  • 90
    Drilling into the exception does nothing. It just says there is a DbEntityValidationResult but does not let you expand!! – Shumii Aug 28 '12 at 15:45
  • 32
    @Shumii See [this answer](http://stackoverflow.com/a/6593432/1080891) to expand the exception. – Cavyn VonDeylen Oct 23 '12 at 19:06
  • 19
    Just to extend an elegant solution. You may want to override the savechanges method in your own DbContext class, and then add try catch block, where the try block just try to save (base.SaveChanges()), and the catch block catches only DbEntityValidationException. This way, you don't need to add it in every place you save your changes. – Milton Aug 08 '13 at 12:59
  • Is it possible to get the value of the offending property? – Leonardo Herrera Dec 22 '13 at 00:26
  • 9
    This has saved my bacon on more than one occasion. I could only upvote once. Wished they'd let me upvote for every time I've copied and pasted this. – Damon Drake Dec 31 '13 at 22:42
  • 7
    +2 for the code. Indeed a savior :) -1 for using `Console.WriteLine`, I estimate more people are writing web projects then console apps nowadays, and `Debug.Write` works in both... – Bart May 13 '14 at 07:51
  • This was new thing i now know, EntityValidationErrors property is not accessible if I catch general exception. Thanks. – Jsinh Jul 31 '14 at 08:17
  • 2
    @LeonardoHerrera: Your question is very old but only recently I found how to get the value of the offending property: `eve.Entry.CurrentValues.GetValue(ve.PropertyName)` (see also the Edit section in my answer above). – Slauma Oct 16 '14 at 20:02
  • This was really helpful, but instead of overloading the Entity Context I edited my database.Context.tt file to auto generate the savechanges overload. – Tod Jan 15 '15 at 11:03
  • They ought to fix this. The amount of time I've wasted looking this up again and again. – Ian Warburton Apr 18 '15 at 16:09
  • If the problem is seeding data, you can use this in your seed core to debug and watch validation errors: http://stackoverflow.com/questions/16718510/debugging-package-manager-console-update-database-seed-method – Sebastián Rojas Jun 10 '15 at 18:14
  • Thanks! My error was: "User name my@email.com is already taken." When i tried to create a new entry (many to many relationship). – Jo Smo Jul 04 '15 at 19:47
  • I found this code didn't work when the invalid property was a ComplexType. See my answer below for an updated version that handles this case. – mikesigs Sep 30 '15 at 05:37
  • thanks. this helped me to exactly pin point the issue. I had required attribute in one of the properties in the entity but i was not passing the values so this exception was being thrown. I was struggling to find out what was causing the issue. – ziaprog Dec 08 '17 at 07:51
  • @Slauma Thanks man, I really appreciate your work, Very good answer.Thanks a lot. – Brijesh Mavani May 17 '18 at 06:07
  • Since I was running into this problem in a unit test, it took a while to figure out that I needed to add a reference to System.Data assembly and using System.Data.Entity.Validation statement. – Yazan Khalaileh Apr 23 '19 at 17:27
  • Kind of annoying that `DbEntityValidationException` doesn't include this data in its `ToString` – xr280xr Jan 06 '20 at 19:02
495

You can do it from Visual Studio during debugging without writing any code, not even a catch block.

Just add a watch with the name:

((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors

The watch expression $exception displays any exception thrown in the current context, even if it has not been caught and assigned to a variable.

Based on http://mattrandle.me/viewing-entityvalidationerrors-in-visual-studio/

shA.t
  • 16,580
  • 5
  • 54
  • 111
yoel halb
  • 12,188
  • 3
  • 57
  • 52
  • 45
    +1 Way better solution, and does not require changes to code. Cool – Justas Jul 07 '14 at 23:28
  • 4
    +1 this is so very, very handy! You don't even need to have a try/catch block. Just stick this in the watch list when VS breaks and voila.. you've got the validation errors in front of you. – theyetiman Nov 05 '14 at 15:46
  • 41
    a couple of times a year I forget how to do this and find this answer – Justin Moore Apr 29 '15 at 15:13
  • When I debug vb.net code, the watch window gives a value of "Character is not valid." Is there a difference between C# and VB watch expressions? – Zairja Jul 14 '15 at 18:41
  • 3
    @zairja I haven't tested it in vb.net, but it appears that the variable is defined for vb.net as well in https://msdn.microsoft.com/en-us/library/ms164891.aspx, however the cast is probably not defined for vb.net, and instead you should probably do DirectCast ($exception,System.Data.Entity.Validation.DbEntityValidationException) – yoel halb Jul 16 '15 at 19:31
  • 2
    I know that "thanks" are not welcome in comments but for the sake of preventing me hours of wasted time... thanks! – Carlo Luther Apr 28 '16 at 17:28
  • 2
    throws not in context error when i try to add this expression – ziaprog Dec 08 '17 at 07:54
  • Same issue as @ziaprog mentioned ^. But silverfox1948's solution worked for me - context.GetValidationErrors() – Kon Feb 02 '18 at 16:00
  • This is the best and most elegant approach that works! It saves you time, no code change. Thanks! – Alexander Jun 25 '18 at 14:45
  • Excellent, thank you. It helped me solve an problem whereby I had incorrectly defined a column in a table. – SteveP Dec 12 '19 at 16:57
  • quick useful answer. cool! – funbrain9 Sep 21 '21 at 02:03
118

This could actually do it without having to write code:

In your catch block, add a break point at the following line of code:

catch (Exception exception)
{

}

Now if you hover on exception or add it to the Watch and then navigate into the exception details as shown below; you will see which particular column(s) is/ are causing the problem as this error usually occurs when a table-constraint is violated..

enter image description here

Large image

t_plusplus
  • 4,079
  • 5
  • 45
  • 60
59

Here's how you can check the contents of the EntityValidationErrors in Visual Studio (without writing any extra code) i.e. during Debugging in the IDE.

The Problem?

You are right, the Visual Studio debugger's View Details Popup doesn't show the actual errors inside the EntityValidationErrors collection .

enter image description here

The Solution!

Just add the following expression in a Quick Watch window and click Reevaluate.

((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors

In my case, see how I am able to expand into the ValidationErrors List inside the EntityValidationErrors collection

enter image description here

References: mattrandle.me blog post, @yoel's answer

Community
  • 1
  • 1
Shiva
  • 20,575
  • 14
  • 82
  • 112
40

For a quick way to see the first error without even adding a watch you can paste this in the Immediate Window:

((System.Data.Entity.Validation.DbEntityValidationException)$exception)
    .EntityValidationErrors.First()
    .ValidationErrors.First()
djdmbrwsk
  • 582
  • 5
  • 10
  • 2
    You can also use $exception.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.ErrorMessage) to get all of them :) imho using the immediate window is the best answer – chrispepper1989 Dec 18 '17 at 11:03
17

For anyone who works in VB.NET

Try
Catch ex As DbEntityValidationException
    For Each a In ex.EntityValidationErrors
        For Each b In a.ValidationErrors
            Dim st1 As String = b.PropertyName
            Dim st2 As String = b.ErrorMessage
        Next
    Next
End Try
Jack Allen
  • 549
  • 2
  • 5
  • 19
nghiavt
  • 423
  • 5
  • 14
12

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

or:

((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors

If you are not in a try/catch or don't have access to the exception object.

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.

GONeale
  • 26,302
  • 21
  • 106
  • 149
10

If you are simply catching a generic exception, it may benefit you to cast this as a DbEntityValidationException. This type of an exception has a Validation Errors property, and continuing to expand your way into them, you will find all the problems.

For example, if you put a break point in the catch, you can throw the following into a watch:

((System.Data.Entity.Validation.DbEntityValidationException ) ex)

An example of an error is if a field does not allow nulls, and you have a null string, you'll see it say that the field is required.

Greg
  • 2,410
  • 21
  • 26
9

just Check Your Database Table Field Length . Your Input Text Is Greater than the length of column field data type length

Hardeep Singh
  • 818
  • 9
  • 14
9

The answer from @Slauma is really great but I found that it didnt't work when a ComplexType property was invalid.

For example, say you have a property Phone of the complex type PhoneNumber. If the AreaCode property is invalid, the property name in ve.PropertyNames is "Phone.AreaCode". This causes the call to eve.Entry.CurrentValues<object>(ve.PropertyName) to fail.

To fix this, you can split the property name at each ., then recurse through the resulting array of property names. Finally, when you arrive at the bottom of the chain, you can simply return the value of the property.

Below is @Slauma's FormattedDbEntityValidationException class with support for ComplexTypes.

Enjoy!

[Serializable]
public class FormattedDbEntityValidationException : Exception
{
    public FormattedDbEntityValidationException(DbEntityValidationException innerException) :
        base(null, innerException)
    {
    }

    public override string Message
    {
        get
        {
            var innerException = InnerException as DbEntityValidationException;
            if (innerException == null) return base.Message;

            var sb = new StringBuilder();

            sb.AppendLine();
            sb.AppendLine();
            foreach (var eve in innerException.EntityValidationErrors)
            {
                sb.AppendLine(string.Format("- Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                    eve.Entry.Entity.GetType().FullName, eve.Entry.State));
                foreach (var ve in eve.ValidationErrors)
                {
                    object value;
                    if (ve.PropertyName.Contains("."))
                    {
                        var propertyChain = ve.PropertyName.Split('.');
                        var complexProperty = eve.Entry.CurrentValues.GetValue<DbPropertyValues>(propertyChain.First());
                        value = GetComplexPropertyValue(complexProperty, propertyChain.Skip(1).ToArray());
                    }
                    else
                    {
                        value = eve.Entry.CurrentValues.GetValue<object>(ve.PropertyName);
                    }
                    sb.AppendLine(string.Format("-- Property: \"{0}\", Value: \"{1}\", Error: \"{2}\"",
                        ve.PropertyName,
                        value,
                        ve.ErrorMessage));
                }
            }
            sb.AppendLine();

            return sb.ToString();
        }
    }

    private static object GetComplexPropertyValue(DbPropertyValues propertyValues, string[] propertyChain)
    {
        var propertyName = propertyChain.First();
        return propertyChain.Count() == 1 
            ? propertyValues[propertyName] 
            : GetComplexPropertyValue((DbPropertyValues)propertyValues[propertyName], propertyChain.Skip(1).ToArray());
    }
}
mikesigs
  • 10,491
  • 3
  • 33
  • 40
  • 2
    I can't believe more people haven't upvoted this one, as it's a very real scenario and it's been driving me nuts the past two nights. You know that feeling you get when you realize your error handling is what's actually throwing the error? Ugh. – DJ Grossman Jun 23 '17 at 10:23
9

In debug, you can enter this in your QuickWatch expression evaluator entry field:

context.GetValidationErrors()
shA.t
  • 16,580
  • 5
  • 54
  • 111
silverfox1948
  • 857
  • 10
  • 15
9

Was also struggling with this error and based on the topic here and this answer was able to figure out snippet to copy/paste without the need to figure out what has to be imported (excellent for C# beginners), code below:

try
{
  context.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException ex)
{
  foreach (var entityValidationErrors in ex.EntityValidationErrors)
  {
    foreach (var validationError in entityValidationErrors.ValidationErrors)
    {
      System.Diagnostics.Debug.WriteLine("Property: " + validationError.PropertyName + " Error: " + validationError.ErrorMessage);
    }
  }
}
Daniel Danielecki
  • 8,508
  • 6
  • 68
  • 94
8

I had to write this in the Immediate window :3

(((exception as System.Data.Entity.Validation.DbEntityValidationException).EntityValidationErrors as System.Collections.Generic.List<System.Data.Entity.Validation.DbEntityValidationResult>)[0].ValidationErrors as System.Collections.Generic.List<System.Data.Entity.Validation.DbValidationError>)[0]

in order to get deep into the exact error !

EDIT: Apparently there is a shorter and better version to get all errors, not just the first:

$exception.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.ErrorMessage)

Nour
  • 5,252
  • 3
  • 41
  • 66
8

Note that Entity.GetType().BaseType.Name gives the type name you specified, not the one with all the hex digits in its name.

Eric Nelson
  • 763
  • 1
  • 8
  • 17
7

Per @Slauma's answer and @Milton's suggestion I've extended our base class's custom save method with a try/catch that will handle (and hence log in our error logging!) these sorts of exceptions.

// Where `BaseDB` is your Entities object... (it could be `this` in a different design)
public void Save(bool? validateEntities = null)
{
    try
    {
        //Capture and set the validation state if we decide to
        bool validateOnSaveEnabledStartState = BaseDB.Configuration.ValidateOnSaveEnabled;
        if (validateEntities.HasValue)
            BaseDB.Configuration.ValidateOnSaveEnabled = validateEntities.Value;

        BaseDB.SaveChanges();

        //Revert the validation state when done
        if (validateEntities.HasValue)
            BaseDB.Configuration.ValidateOnSaveEnabled = validateOnSaveEnabledStartState;
    }
    catch (DbEntityValidationException e)
    {
        StringBuilder sb = new StringBuilder();
        foreach (var eve in e.EntityValidationErrors)
        {
            sb.AppendLine(string.Format("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:", 
                                            eve.Entry.Entity.GetType().Name,
                                            eve.Entry.State));
            foreach (var ve in eve.ValidationErrors)
            {
                sb.AppendLine(string.Format("- Property: \"{0}\", Error: \"{1}\"",
                                            ve.PropertyName,
                                            ve.ErrorMessage));
            }
        }
        throw new DbEntityValidationException(sb.ToString(), e);
    }
}
jocull
  • 20,008
  • 22
  • 105
  • 149
6

Using the answer of @Slauma i have made a code snippet (a surrounds with snippet) for better use.

<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <SnippetTypes>
        <SnippetType>SurroundsWith</SnippetType>
      </SnippetTypes>
      <Title>ValidationErrorsTryCatch</Title>
      <Author>Phoenix</Author>
      <Description>
      </Description>
      <HelpUrl>
      </HelpUrl>
      <Shortcut>
      </Shortcut>
    </Header>
    <Snippet>
      <Code Language="csharp"><![CDATA[try
{
    $selected$ $end$
}
catch (System.Data.Entity.Validation.DbEntityValidationException e)
{
    foreach (var eve in e.EntityValidationErrors)
    {
        Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
            eve.Entry.Entity.GetType().Name, eve.Entry.State);
        foreach (var ve in eve.ValidationErrors)
        {
            Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
                ve.PropertyName, ve.ErrorMessage);
        }
    }
    throw;
}]]></Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>
Phoenix_uy
  • 3,173
  • 9
  • 53
  • 100
5

Catch the exception in a try catch and then quick watch or ctrl+d & ctrl+q and you can drill down to the EntityValidationErrors.

Brandon.Staley
  • 1,742
  • 21
  • 25
5

Just throwing my two cents in...

Within my dbConfiguration.cs, I like to wrap my context.SaveChanges() method into a try/catch and produce an output text file that allows me to read the Error(s) clearly, and this code also timestamps them - handy if you run into more than one error at different times!

        try
        {
            context.SaveChanges();
        }
        catch (DbEntityValidationException e)
        {
            //Create empty list to capture Validation error(s)
            var outputLines = new List<string>();

            foreach (var eve in e.EntityValidationErrors)
            {
                outputLines.Add(
                    $"{DateTime.Now}: Entity of type \"{eve.Entry.Entity.GetType().Name}\" in state \"{eve.Entry.State}\" has the following validation errors:");
                outputLines.AddRange(eve.ValidationErrors.Select(ve =>
                    $"- Property: \"{ve.PropertyName}\", Error: \"{ve.ErrorMessage}\""));
            }
            //Write to external file
            File.AppendAllLines(@"c:\temp\dbErrors.txt", outputLines);
            throw;
        }
IfElseTryCatch
  • 483
  • 9
  • 12
5

What i found...when i got 'EntityValidationErrors' error is that....i have a field in my database 'db1' in table 'tbladdress' as 'address1' which has size of 100 (i.e address varchar(100) null) and i was passing value more than 100 characters..and this leading to error while saving data to database....

So you must Check the data you are passing to the field.

  • 1
    I appreciate this answer because it actually helped me resolve my error. The table I was saving to in my db had all `not null` columns so once I added data to all elements prior to my `db.SaveChanges()` I received no error. – BinaryJoe01 Oct 17 '17 at 15:17
3

This works for me.

var modelState = ModelState.Values;
if (!ModelState.IsValid)
{
    return RedirectToAction("Index", "Home", model);
}

Put a breakpoint on if statement. Then you can check modelState in debug windows. On every value you can see if there is an error and even the error message. That's it. When you don't need it anymore, just delete or comment the line.

I hope this will help.

If asked, I can provide detailed screenshot in the debug window.

AngelDown
  • 291
  • 2
  • 4
3

As mentioned in other posts, simply catch the exception in DbEntityValidationException class. Which will give you watever you required during error cases.

 try
 {
  ....
 }
 catch(DbEntityValidationException ex)
 {
  ....
 }
Sanoop Surendran
  • 3,484
  • 4
  • 28
  • 49
Mayank
  • 43
  • 1
  • 11
3

Here's another way to do it instead of using foreach loops for looking inside EntityValidationErrors. Of course you can format the message to your own liking :

try {
        // your code goes here...
    } 
catch (DbEntityValidationException ex) 
    {
        Console.Write($"Validation errors: {string.Join(Environment.NewLine, ex.EntityValidationErrors.SelectMany(vr => vr.ValidationErrors.Select(err => $"{err.PropertyName} - {err.ErrorMessage}")))}", ex);
        throw;
    }
Quantum_Joe
  • 181
  • 5
3

In my case it was because of the length of the database field is less than the length of the input field.

database table

create table user(
  Username nvarchar(5) not  null
);

My input

User newUser = new User()
{
   Username = "123456"
};

the value for Username length is 5 which is lessthan 6

...this may help someone

Community
  • 1
  • 1
Qwerty
  • 578
  • 1
  • 5
  • 31
2

I faced this error before

when I tried to update specific field in my model in entity framwork

Letter letter = new Letter {ID = letterId, ExportNumber = letterExportNumber,EntityState = EntityState.Modified};
LetterService.ChangeExportNumberfor(letter);
//----------


public int ChangeExportNumber(Letter letter)
    {
        int result = 0;
        using (var db = ((LettersGeneratorEntities) GetContext()))
        {
            db.Letters.Attach(letter);
            db.Entry(letter).Property(x => x.ExportNumber).IsModified = true;
            result += db.SaveChanges();
        }
        return result;
    }

and according the above answers

I found the Validation message The SignerName field is required.

which pointing to field in my model

and when I checked my database schema I found

enter image description here

so off coure ValidationException has its right to raise

and according to this field I want it to be nullable, (I dont know how I messed it)

so I changed that field to allow Null, and by this my code will not give me this error again

so This error maybe will happened if you invalidate Your Data integrity of your database

Community
  • 1
  • 1
Basheer AL-MOMANI
  • 14,473
  • 9
  • 96
  • 92
  • 1
    Whether or not an exception should be raised is not the point here. Next, you're cutting some corners here. When a field is required in the database schema you need more than that to have a `DbEntityValidationException` raised. – Gert Arnold Sep 04 '16 at 13:35
2

Please check the fields value you are passing, are valid and according to database fields. For example number of characters passed in a particular field are less than the characters defined in database table field.

Sitecoredev
  • 145
  • 1
  • 3
  • 16
1

If you're using IIS with Windows Authentification and Entity Framework, be careful to use authorize.

I tried to POST without authorize and it didn't work, and get this error on db.SaveChangesAsync();, while all other verbs GET and DELETE were working.

But when I added AuthorizeAttribute as annotation, it worked.

[Authorize]
public async Task<IHttpActionResult> Post(...){
....
}
Toodoo
  • 8,570
  • 6
  • 35
  • 58
1

This error occurs mostly because of field size. CHECK all the field sizes in a database table.

Alexander Zaldostanov
  • 2,907
  • 4
  • 30
  • 39
0

Check whether you have Not Null constraint in your table columns and you are not passes the value for that column while insert/Update operations. That Causes this exception in entity framework.

s Jagathish
  • 57
  • 1
  • 10
0

I also faced the same problem. I updated my .edmx from the database after that the exception has vanished.

HariChintha
  • 37
  • 1
  • 9