Getting exact error type in from DbValidationException

后端 未结 6 1027
闹比i
闹比i 2020-12-02 03:24

I have the situation where I\'m initializing my model in DatabaseInitializer() for EF 4.1 and get this annoying error \"Validation failed for one or more entities. See

相关标签:
6条回答
  • 2020-12-02 03:48

    I found it useful to create a SaveChanges wrapper which makes the EntityValidationErrors more readable:

    Public Sub SaveChanges(entities As Entities)
    
        Try
            entities.SaveChanges()
    
        Catch ex As DbEntityValidationException
    
            Dim msg As New StringBuilder
            msg.AppendLine(ex.Message)
    
            For Each vr As DbEntityValidationResult In ex.EntityValidationErrors
                For Each ve As DbValidationError In vr.ValidationErrors
                    msg.AppendLine(String.Format("{0}: {1}", ve.PropertyName, ve.ErrorMessage))
                Next
            Next
    
            Throw New DbEntityValidationException(msg.ToString, ex.EntityValidationErrors, ex)
    
        End Try
    
    End Sub
    

    and then changed 'entities.SaveChanges()' to 'SaveChanges(entities)' in my entire project

    0 讨论(0)
  • 2020-12-02 03:52

    Well, I had same problem. My model worked good in EF CTP5 but failed to build in 4.1 with the same error ""Validation failed for one or more entities" when I tried to initalize it. I figured out that I had property:

    public string Comment {get; set;}
    

    Then in seed method in overrided initializer, I had quite a bit long (about 600 letters) comment.

    I think the point is: in EF 4.1 you have to set data annotations explicitly in some cases. For me, setting:

    [StringLength(4000)] 
    public string Comment {get; set;}
    

    helped. It's weird since CTP5 had no problems with that.

    0 讨论(0)
  • 2020-12-02 03:55

    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
    
    0 讨论(0)
  • 2020-12-02 03:57

    The best solution in my opinion, is to handle this kind of errors in a centralized way.

    just add this method to the main DbContext class :

    public override int SaveChanges()
    {
        try
        {
            return base.SaveChanges();
        }
        catch (DbEntityValidationException ex)
        {
            string errorMessages = string.Join("; ", ex.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.PropertyName + ": " + x.ErrorMessage));
            throw new DbEntityValidationException(errorMessages);
        }
    }
    

    This will overwrite your context's SaveChanges() method and you'll get a comma separated list containing all the entity validation errors.

    hope this is helpful.

    0 讨论(0)
  • I know it's an old question but here's my answer:

    catch (DbEntityValidationException ex)
       {
        String.Join("\n", ex.EntityValidationErrors
              .SelectMany(x => x.ValidationErrors)
              .Select(x => x.ErrorMessage)
              .ToArray());
       }
    

    and if you use code first, you can also globalize your error messages using multiple resource files

    For instance I have these two seperate resource file, one for error and one for property name and I use them as following:

    public class Person 
        {
            [Required(ErrorMessageResourceName = "required",ErrorMessageResourceType =typeof(ErrorMessages))]
            [MaxLength(100,ErrorMessageResourceName = "maxLength", ErrorMessageResourceType = typeof(ErrorMessages))]
            [Display(Name = "FirstName",ResourceType = typeof(Properties))]
            public string FirstName { get; set; }
             }
    

    As you can see I have completely translated my error messages including the properties names, so I could then use them in the user later for instance:

    0 讨论(0)
  • 2020-12-02 04:15

    You could try this in a try/catch block?

    catch (DbEntityValidationException dbEx)
    {
        foreach (var validationErrors in dbEx.EntityValidationErrors)
        {
            foreach (var validationError in validationErrors.ValidationErrors)
            {
                Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题