DbValidationException에서 정확한 오류 유형 가져 오기


184

EF 4.1 용 DatabaseInitializer ()에서 모델을 초기화 하고이 성가신 오류가 발생 "Validation failed for one or more entities. See 'EntityValidationErrors' property for more details."하는 상황이 있으므로이 EntityValidationErrors로 이동 {System.Data.Entity.Validation.DbEntityValidationResult}하여 초기화 할 수없는 필드에 대한 정보를 전혀 제공하지 않는 필드가 있습니다. . 이 오류에 대한 자세한 정보를 얻을 수있는 방법이 있습니까?

사물을 지우려면 :

문자열 길이 문제를 해결하는 방법을 알고 있습니다. 내가 묻는 것은 모델을 깨뜨리는 정확한 필드 이름을 얻는 방법입니다.

답변:


377

catch {...}블록 내에서 디버그 모드에있는 동안 "QuickWatch"창 ( ctrl+ alt+ q)을 열고 여기에 붙여 넣으십시오.

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

그러면 ValidationErrors트리 로 드릴 다운 할 수 있습니다 . 이 오류에 대한 즉각적인 통찰력을 얻는 가장 쉬운 방법입니다.

첫 번째 오류에만 관심이 있고 catch블록 이없는 Visual 2012+ 사용자의 경우 다음을 수행 할 수도 있습니다.

((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors.First().ValidationErrors.First().ErrorMessage

9
이것은 다른 답변보다 낫습니다 :)
Doug

98
당신이 catch 블록이없는 경우 대체 할 수 ex$exception같은 결과를 얻을.
Ecyrb

또한 당신이 대체 만든다 ex/ 전자 승으로 catch (Exception THIS)이다
Eonasdan

@ Ecyrb, 감사합니다. 인터넷 검색 시간을 절약했습니다. 또한 유효성 검사 오류 수가 1로 표시 되더라도 실제로 배열에는 두 개의 오류가있는 두 개의 요소가 있습니다.
매트릭스

3
System.Linq를 참조하지 않고 즉시 창을 사용하는 경우 :System.Linq.Enumerable.ToList(System.Linq.Enumerable.ToList(((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors)[0].ValidationErrors)[0].ErrorMessage
jpsimard-nyx

124

try / catch 블록에서 시도해 볼 수 있습니까?

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);
        }
    }
}

11

내 생각에 가장 좋은 해결책은 이러한 종류의 오류를 중앙 집중식으로 처리하는 것입니다.

이 메소드를 기본 DbContext클래스에 추가하십시오 .

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);
    }
}

컨텍스트의 SaveChanges()메서드를 덮어 쓰고 모든 엔터티 유효성 검사 오류가 포함 된 쉼표로 구분 된 목록이 표시됩니다.

이것이 도움이되기를 바랍니다.


4

글쎄, 나는 같은 문제가 있었다. 내 모델은 EF CTP5에서 잘 작동했지만 초기화하려고 할 때 "하나 이상의 엔터티에 대한 유효성 검사에 실패했습니다"라는 오류와 함께 4.1에서 빌드하지 못했습니다.

public string Comment {get; set;}

그런 다음 재정의 된 이니셜 라이저의 시드 방법에서 꽤 긴 (약 600 자) 주석이있었습니다.

요점은 다음과 같습니다. EF 4.1 에서는 경우에 따라 데이터 주석을 명시 적으로 설정 해야 합니다. 나를 위해 설정 :

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

도와주었습니다. CTP5에 아무런 문제가 없었기 때문에 이상합니다.


내가 묻는 것은 모델을 깨는 정확한 속성 이름을 얻는 방법입니다. 그러나 (StringLength (Int32.MaxValue)]를 내 속성의 속성으로 사용하여 언급 한 문제를 극복 할 수 있었지만 (Ladislav Mrnka가 제안한 대로이 질문에 대해 이야기했습니다. stackoverflow.com/questions/5346155/… ) Powodzenia! =)
Naz

4.1에서 모델에 새 속성을 추가했을 때 발생했습니다. 4.1 이전에 완벽하게 작동했습니다. 기묘한. 모델의 모든 속성에 주석을 추가하여 해결되었습니다.
Roberto Bonini

1

EntityValidationErrors를 더 읽기 쉽게 만드는 SaveChanges 래퍼를 만드는 것이 유용하다는 것을 알았습니다.

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

그런 다음 전체 프로젝트에서 'entities.SaveChanges ()'를 'SaveChanges (entities)'로 변경했습니다.


0

나는 그것이 오래된 질문이라는 것을 알고 있지만 여기 내 대답이 있습니다.

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

코드를 먼저 사용하는 경우 여러 리소스 파일을 사용하여 오류 메시지를 전역화할 수도 있습니다.

예를 들어이 두 개의 별도 리소스 파일 (오류 및 속성 이름)이 있으며 다음과 같이 사용합니다. 여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오

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; }
         }

보시다시피 속성 이름을 포함하여 오류 메시지를 완전히 번역 했으므로 나중에 예를 들어 사용자에서 사용할 수 있습니다.

여기에 이미지 설명을 입력하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.