하나 이상의 엔터티에 대한 유효성 검사에 실패했습니다. 자세한 내용은 'EntityValidationErrors'속성을 참조하십시오.


804

코드 우선 접근 방식으로 데이터베이스를 시드 할 때이 오류가 발생합니다.

하나 이상의 엔터티에 대한 유효성 검사에 실패했습니다. 자세한 내용은 'EntityValidationErrors'속성을 참조하십시오.

솔직히 유효성 검사 오류의 내용을 확인하는 방법을 모르겠습니다. Visual Studio는 8 개의 객체가있는 배열이므로 8 개의 유효성 검사 오류가 있음을 보여줍니다.

이것은 이전 모델에서 작동했지만 아래에서 설명하는 몇 가지 사항을 변경했습니다.

  • Status라는 열거 형이 있는데 Status라는 클래스로 변경했습니다.
  • ApplicantsPositionHistory 클래스를 동일한 테이블에 2 개의 외래 키를 갖도록 변경했습니다.

긴 코드로 실례하지만 모든 것을 붙여 넣어야합니다. 다음 코드의 마지막 줄에서 예외가 발생합니다.

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

답변:


1237

솔직히 유효성 검사 오류의 내용을 확인하는 방법을 모르겠습니다. Visual Studio는 8 개의 객체가있는 배열이므로 8 개의 유효성 검사 오류가 있음을 보여줍니다.

실제로 디버그 중에 Visual Studio에서 해당 배열로 드릴하면 오류가 표시됩니다. 그러나 예외를 포착 한 다음 일부 로깅 저장소 또는 콘솔에 오류를 기록 할 수도 있습니다.

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는 성공적으로 검증 할 수없는 엔티티를 나타내는 콜렉션이며 엔티티 ValidationErrors당 내부 콜렉션 은 특성 레벨의 오류 목록입니다.

이러한 유효성 검사 메시지는 일반적으로 문제의 원인을 찾을 수있을 정도로 유용합니다.

편집하다

약간의 개선 사항 :

위반 속성 의 은 다음과 같이 내부 루프에 포함될 수 있습니다.

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

콘솔 응용 프로그램뿐만 아니라 모든 응용 프로그램에서 작동하기 때문에 디버깅 Debug.Write이 바람직 할 수 있습니다 Console.WriteLine(아래 주석에서 @Bart 덕분에).

프로덕션 환경에 있고 예외 로깅에 Elmah 를 사용하는 웹 응용 프로그램의 SaveChanges경우이 새 예외를 발생시키기 위해 사용자 지정 예외를 만들고 덮어 쓰는 것이 매우 유용한 것으로 나타났습니다 .

사용자 정의 예외 유형은 다음과 같습니다.

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

그리고 SaveChanges다음과 같은 방법으로 덮어 쓸 수 있습니다 :

public class MyContext : DbContext
{
    // ...

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

몇 가지 말 :

  • Elmah가 웹 인터페이스 또는 전송 된 전자 메일 (구성한 경우)에 표시되는 노란색 오류 화면에 메시지 상단에 직접 유효성 검사 세부 정보가 표시됩니다.

  • 덮어 쓰기 Message대신 사용자 지정 예외에서 속성을 덮어 쓰면 ToString()표준 ASP.NET "YSOD (Yellow screen of death)"도이 메시지를 표시하는 이점이 있습니다. Elmah와 달리 YSOD는 분명히을 사용하지 ToString()않지만 둘 다 Message속성을 표시합니다 .

  • 원본 DbEntityValidationException을 내부 예외로 래핑하면 원본 스택 추적을 계속 사용할 수 있으며 Elmah 및 YSOD에 표시됩니다.

  • 줄에 중단 점을 설정하면 약간 어색하고 모든 사람에게 쉽게 작동하지 않는 유효성 검사 모음으로 드릴하는 대신 속성을 텍스트로 throw newException;간단하게 검사 할 수 있습니다 newException.Message(아래 주석 참조).


87
예외에 대한 드릴 작업은 아무 것도 수행하지 않습니다. DbEntityValidationResult가 있지만 확장 할 수는 없습니다!
Shumii

30
@Shumii 예외를 확장하려면 이 답변 을 참조하십시오 .
Cavyn VonDeylen

18
우아한 솔루션을 확장하십시오. 자체 DbContext 클래스에서 savechanges 메소드를 대체 한 다음 try catch 블록을 추가하십시오. 여기서 try 블록은 저장을 시도하고 (base.SaveChanges ()) catch 블록은 DbEntityValidationException 만 포착합니다. 이렇게하면 변경 사항을 저장하는 모든 위치에 추가 할 필요가 없습니다.
Milton

7
이로 인해 베이컨이 두 번 이상 절약되었습니다. 한 번만 투표 할 수있었습니다. 내가 이것을 복사하여 붙여 넣을 때마다 그들이 나를 투표하도록하겠습니다.
데이먼 드레이크

5
코드 +2 실제로 사용하는 구세주 :) -1 Console.WriteLine, 더 많은 사람들이 요즘 웹 프로젝트를 작성하고 앱을 콘솔로 작성하고 Debug.Write있으며 둘 다에서 작동 한다고 추정 합니다.
Bart

459

catch 블록이 아닌 코드를 작성하지 않고도 디버깅 중에 Visual Studio에서이를 수행 할 수 있습니다.

이름이있는 시계를 추가하기 만하면됩니다.

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

watch 표현식 $exception은 변수에 지정되지 않았거나 현재 컨텍스트에서 발생한 예외를 표시합니다.

http://mattrandle.me/viewing-entityvalidationerrors-in-visual-studio/ 기반


39
+1 더 나은 솔루션이며 코드를 변경할 필요가 없습니다. 쿨
Justas

4
+1 매우 편리합니다! try / catch 블록이 없어도됩니다. VS가 중단되고 보일 때이 목록을 감시 목록에 추가하면됩니다. 앞에 검증 오류가 있습니다.
theyetiman

40
일 년에 몇 번 나는 이것을하는 방법을
Justin Moore

3
@zairja vb.net에서 테스트하지 않았지만 변수는 msdn.microsoft.com/en-us/library/ms164891.aspx 에서도 vb.net에 대해 정의 된 것으로 보이지만 캐스트는 아마 아닙니다 vb.net에 대해 정의되었으며 대신 DirectCast ($ exception, System.Data.Entity.Validation.DbEntityValidationException)를 수행해야합니다.
yoel halb

2
"감사"는 의견에 환영받지 못하지만 시간 낭비를 막기 위해 ... 감사합니다!
루터

105

실제로 코드를 작성하지 않고도 수행 할 수 있습니다.

캐치 블록에서 다음 코드 줄에 중단 점을 추가하십시오.

catch (Exception exception)
{

}

이제 위에 마우스를 올려 exception놓거나에 추가 Watch한 다음 아래에 표시된 예외 세부 정보를 탐색하십시오. 이 오류는 일반적으로 테이블 제약 조건을 위반할 때 발생하므로 어떤 특정 열에서 문제를 일으키는 지 알 수 있습니다.

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

큰 이미지


4
이 방법은 매우 간단하며 IDE를 활용합니다. :
dsnunez

3
이것은 빠르고 간단하며 IDE를 사용하며 많은 시간을 절약했기 때문에 좋은 솔루션입니다.
maxshuty가

2
이런 식으로 같은 나는 "어떻게 코더하고 코드를 할 수 없습니다"
개방하고 무료

1
감사합니다. 이것은 간단하지만 IDE를 사용하여 예외를 보는 것이 좋습니다.
Thomas. 벤츠

완벽한 솔루션
Neeraj 싱 Chouhan

46

다음 은 IDE 에서 디버깅 하는 동안 (추가 코드를 작성하지 않고) Visual Studio 에서 EntityValidationErrors 의 내용을 확인하는 방법 입니다.

문제?

맞습니다 .Visual Studio 디버거의 세부 정보보기 팝업에는 EntityValidationErrors컬렉션 내부의 실제 오류가 표시되지 않습니다 .

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

해결책!

Quick Watch 창 에 다음 표현식을 추가하고 재평가를 클릭하십시오 .

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

내 경우 ValidationErrors List에는 EntityValidationErrors컬렉션 내부 로 확장하는 방법을 참조하십시오

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

참고 문헌 : mattrandle.me 블로그 게시물 , @yoel 의 답변


3
왜이 문제가 해결되지 않았습니까? 그것은 다른 것이 아니라 오류를 보여 주어야합니다
Geomorillo

2
유효성 검사 오류는 속성 오류를 보여줍니다 (예 : 주제 필드는 필수, 좋은 답변입니다, 감사합니다
hamzeh.hanandeh

1
큰! 내 밤을 구했어! :)
Patrick

1
이것은 시계의 정확한 오류를 시각화하는 현명한 방법입니다 ... 감사합니다!
Qwerty 2016 년

39

시계를 추가하지 않고도 첫 번째 오류를 빠르게 확인할 수있는 방법은 직접 실행 창에 붙여 넣을 수 있습니다.

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

1
$ exception.EntityValidationErrors.SelectMany (x => x.ValidationErrors) .Select (x => x.ErrorMessage)를 사용하여 모든 것을 얻을 수도 있습니다. 즉시 창을 사용하는 imho가 가장 좋습니다
chrispepper1989

15

일하는 사람을 위해 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

12

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

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

또는:

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

try / catch에 없거나 예외 개체에 액세스 할 수없는 경우

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


10

단순히 일반 예외를 포착하는 경우이를 DbEntityValidationException 으로 캐스트하는 것이 좋습니다 . 이 유형의 예외에는 유효성 검사 오류 속성이 있으며 계속해서 확장하면 모든 문제를 발견 할 수 있습니다.

예를 들어, 캐치에 중단 점을두면 다음을 시계에 던질 수 있습니다.

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

오류의 예는 필드가 널을 허용하지 않고 널 문자열이있는 경우 필드가 필요하다는 메시지가 표시됩니다.


9

데이터베이스 테이블 필드 길이를 확인하십시오. 입력 텍스트가 열 필드 데이터 유형 길이보다 깁니다.


9

디버그에서 QuickWatch 표현식 평가 기 입력 필드에이를 입력 할 수 있습니다.

context.GetValidationErrors()

8

@Slauma의 답변은 정말 훌륭하지만 ComplexType 속성이 유효하지 않으면 작동하지 않는다는 것을 알았습니다.

예를 들어 Phonecomplex type 의 속성 이 있다고 가정합니다 PhoneNumber. 경우 AreaCode속성이 유효하지 않습니다에 속성 이름은 ve.PropertyNames"Phone.AreaCode"입니다. 이로 인해 호출 eve.Entry.CurrentValues<object>(ve.PropertyName)이 실패합니다.

이 문제를 해결하기 위해 각 속성 이름을 분할 .한 다음 결과 속성 이름 배열을 통해 반복 할 수 있습니다 . 마지막으로 체인의 하단에 도착하면 단순히 속성 값을 반환 할 수 있습니다.

다음은 FormattedDbEntityValidationExceptionComplexTypes를 지원하는 @Slauma 클래스입니다.

즐겨!

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

1
나는 이것이 실제 시나리오이고 지난 이틀 밤 나를 미치게 만들었 기 때문에 더 많은 사람들이 이것을 피하지 않았다는 것을 믿을 수 없다. 오류 처리를 인식했을 때 얻는 느낌이 실제로 오류를 일으키는 것임을 알고 있습니까? 어.
DJ Grossman

7

Entity.GetType().BaseType.Name이름에 모든 16 진수가있는 유형이 아니라 지정한 유형 이름 을 제공합니다.


7

@Slauma의 대답과 @Milton의 제안에 따라 이러한 종류의 예외를 처리하고 오류 로그에 기록하는 try / catch로 기본 클래스의 사용자 지정 저장 방법을 확장했습니다.

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

1
sb.AppendFormat ()을 직접 사용할 수 있습니다
Bastien Vandamme

1
AppendFormat을 사용하는 경우에도 개행을 추가해야합니다.
jocull

7

나는 이것을 직접 실행 창에 써야했습니다 : 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]

정확한 오류에 깊이 들어가기 위해!


6

@ Slauma의 대답을 사용하여 더 나은 사용을 위해 코드 스 니펫 (스 니펫으로 둘러싸인)을 만들었습니다.

<?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>

5

try catch에서 예외를 포착 한 다음 quick watch 또는 ctrl + d & ctrl + q를 사용하여 EntityValidationErrors로 드릴 다운 할 수 있습니다.


5

그냥 내 두 센트를 던져 ...

내 dbConfiguration.cs 내에서 context.SaveChanges () 메서드를 try / catch로 래핑하고 오류를 명확하게 읽을 수있는 출력 텍스트 파일을 생성 하고이 코드도 타임 스탬프가 표시됩니다. 다른 시간에 하나 이상의 오류가 발생했습니다!

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

5

내가 찾은 것 ... 'EntityValidationErrors'오류가 발생했을 때 .... 'tbladdress'테이블의 데이터베이스 'db1'에 크기가 100 인 'address1'으로 필드가 있습니다 (예 : varchar (100) null) 그리고 100 개 이상의 문자를 전달했습니다. 데이터를 데이터베이스에 저장하는 동안 오류가 발생했습니다 ....

따라서 필드에 전달할 데이터를 확인해야합니다.


1
이 대답은 실제로 내 오류를 해결하는 데 도움이 되었기 때문에 감사합니다. 내 db에 저장 한 테이블에는 모든 not null열이 있으므로 데이터를 모든 요소에 추가하면 db.SaveChanges()오류가 발생하지 않습니다.
BinaryJoe01

3

이것은 나를 위해 작동합니다.

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

if 문에 중단 점을 둡니다. 그런 다음 디버그 창에서 modelState를 확인할 수 있습니다. 모든 값에서 오류 및 오류 메시지가 있는지 확인할 수 있습니다. 그게 다야. 더 이상 필요하지 않으면 행을 삭제하거나 주석 처리하십시오.

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

요청이 있으면 디버그 창에서 자세한 스크린 샷을 제공 할 수 있습니다.


3

다른 게시물에서 언급했듯이 단순히 DbEntityValidationException 클래스에서 예외를 포착하십시오. 오류가 발생한 경우 필요한 정보를 제공합니다.

 try
 {
  ....
 }
 catch(DbEntityValidationException ex)
 {
  ....
 }

2

나는 전에이 오류에 직면했다

엔티티 프레임 워크에서 모델의 특정 필드업데이트 하려고 할 때

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

위의 답변에 따라

확인 메시지를 찾았습니다 The SignerName field is required.

내 모델에서 필드를 가리키는

데이터베이스 스키마를 확인했을 때

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

쿠어 오프 ValidationException는 올릴 권리가 있습니다

이 필드에 따르면 null을 허용하지 않기를 원합니다 (내가 엉망인 방법을 모르겠습니다)

그래서 Null을 허용하도록 해당 필드를 변경 했으며이 코드 로이 오류가 다시 발생하지 않습니다.

데이터베이스의 데이터 무결성을 무효화하면이 오류가 발생할 수 있습니다.


1
예외가 제기되어야하는지의 여부는 여기서 중요하지 않습니다. 다음으로 여기 모서리를 자릅니다. 데이터베이스 스키마에 필드가 필요한 경우에는 그보다 더 많은 필드가 필요합니다 DbEntityValidationException.
Gert Arnold

2

전달하는 필드 값이 유효하고 데이터베이스 필드에 따라 확인하십시오. 예를 들어 특정 필드에 전달 된 문자 수가 데이터베이스 테이블 필드에 정의 된 문자보다 적습니다.


1

당신이 사용하는 경우 IIS를 함께 윈도우위한 인증엔티티 프레임 워크 사용하기주의 authorize.

나는에 노력 POST권한 부여없이이 일을하지 않았다, 그리고에이 오류가 db.SaveChangesAsync();다른 모든 동사 동안, GET그리고 DELETE일하고 있었다.

그러나 AuthorizeAttribute를 주석으로 추가하면 효과가있었습니다.

[Authorize]
public async Task<IHttpActionResult> Post(...){
....
}

1

EntityValidationErrors 내부를 조사하기 위해 foreach 루프를 사용하는 대신 다른 방법으로 수행 할 수 있습니다. 물론 메시지를 원하는대로 포맷 할 수 있습니다.

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

1

필자의 경우 데이터베이스 필드의 길이가 입력 필드의 길이보다 작기 때문입니다.

데이터베이스 테이블

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

내 입력

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

의 값 Username length5 이며lessthan 6입니다.

... 이것은 누군가를 도울 수 있습니다


0

Not Null테이블 컬럼에 제한 조건이 있고 삽입 / 갱신 조작 중에 해당 컬럼의 값을 전달하지 않는지 점검하십시오 . 엔티티 프레임 워크 에서이 예외가 발생합니다.


0

나는 또한 같은 문제에 직면했다. 예외가 사라진 후 데이터베이스에서 .edmx를 업데이트했습니다.



0

또한이 오류로 어려움을 겪고 있으며 여기의 주제를 기반으로 했으며이 답변 은 가져올 코드 (C # 초보자에게 탁월)를 알 필요없이 복사 / 붙여 넣을 스 니펫을 알아낼 수있었습니다. 아래 코드는 다음과 같습니다.

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