c# - framework - validation failed for one or more entities see entityvalidationerrors property for more details




Не удалось выполнить проверку для одного или нескольких объектов. Дополнительную информацию см. В разделе «Свойство EntityValidationErrors». (17)

Честно говоря, я не знаю, как проверить содержимое ошибок проверки. 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)» также отображает это сообщение. В отличие от Elmah YSOD, по-видимому, не использует ToString() , но оба отображают свойство Message .

  • Обертка исходного DbEntityValidationException как внутреннего исключения гарантирует, что исходная трассировка стека будет по-прежнему доступна и отображается в Elmah и YSOD.

  • Установив throw newException; останова на строке, throw newException; вы можете просто проверить свойство newException.Message как текст вместо того, чтобы сверлить в коллекции проверки, что немного неудобно и, похоже, не работает легко для всех (см. комментарии ниже).

У меня возникает эта ошибка при посеве моей базы данных с первым подходом кода.

Не удалось выполнить проверку для одного или нескольких объектов. Дополнительную информацию см. В разделе Свойство 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
        }
    }
}

В отладке вы можете ввести это в поле ввода оценщика выражения QuickWatch:

context.GetValidationErrors()

Вот как вы можете проверить содержимое EntityValidationErrors в Visual Studio (без написания дополнительного кода), то есть во время отладки в среде IDE .

Эта проблема?

Вы правы, в представлении View EntityValidationErrors отладчика Visual Studio Popup не отображаются фактические ошибки внутри коллекции EntityValidationErrors .

Решение!

Просто добавьте следующее выражение в окно быстрого просмотра и нажмите « Переоценка» .

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

В моем случае посмотрите, как я могу перейти в список ValidationErrors внутри коллекции EntityValidationErrors

Ссылки: http://mattrandle.me/viewing-entityvalidationerrors-in-visual-studio/ mattrandle.me, ответ @ yoel


Вы можете сделать это из Visual Studio во время отладки без написания кода, даже блока catch.

Просто добавьте часы с именем:

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

Выражение watch $exception отображает любое исключение, созданное в текущем контексте, даже если оно не было поймано и не присвоено переменной.

Основано на http://mattrandle.me/viewing-entityvalidationerrors-in-visual-studio/


Если вы используете IIS с Windows Authentification и Entity Framework , будьте осторожны с использованием authorize .

Я попытался выполнить POST без авторизации, и это не сработало, и получите эту ошибку на db.SaveChangesAsync(); , тогда как все остальные глаголы GET и DELETE работают.

Но когда я добавил AuthorizeAttribute в качестве аннотации, это сработало.

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

Если вы просто ловите общее исключение, вам может пригодиться это как исключение DbEntityValidationException . Этот тип исключения имеет свойство Validation Errors и продолжает расширять свой путь в них, вы найдете все проблемы.

Например, если вы поставили точку прерывания в catch, вы можете бросить следующее в часы:

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

Примером ошибки является то, что поле не допускает null, и у вас есть нулевая строка, вы увидите, что это поле требуется.


Как упоминалось в других сообщениях, просто поймайте исключение в классе DbEntityValidationException. Что даст вам все, что вам нужно во время ошибок.

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

Обратите внимание, что Entity.GetType().BaseType.Name дает имя типа, которое вы указали, а не тот, у которого есть все шестнадцатеричные цифры в его имени.


Ответ от @Slauma действительно замечательный, но я обнаружил, что он не работал, когда свойство ComplexType было недействительным.

Например, предположим, что у вас есть Phone с Phone сложного типа PhoneNumber . Если свойство AreaCode недействительно, имя свойства в ve.PropertyNames является «Phone.AreaCode». Это приводит к eve.Entry.CurrentValues<object>(ve.PropertyName) вызова eve.Entry.CurrentValues<object>(ve.PropertyName) .

Чтобы исправить это, вы можете разделить имя свойства на каждом . , а затем рекурсия через результирующий массив имен свойств. Наконец, когда вы достигаете нижней части цепочки, вы можете просто вернуть значение свойства.

Ниже приведен класс @ Slauma FormattedDbEntityValidationException с поддержкой ComplexTypes.

Наслаждайтесь!

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

Поймайте исключение в try catch, а затем быстро просмотрите или ctrl + d & ctrl + q, и вы можете перейти к EntityValidationErrors.


Проверьте значение полей, которые вы передаете, действительны и соответствуют полям базы данных. Например, количество символов, переданных в определенном поле, меньше символов, определенных в поле таблицы базы данных.


Проверьте, нет ли ограничения Not Null в столбцах таблицы, и вы не передаете значение для этого столбца во время операций вставки / обновления. Это вызывает это исключение в структуре сущности.


Что я нашел ... когда я получил ошибку EntityValidationErrors, это то, что .... у меня есть поле в моей базе данных «db1» в таблице «tbladdress» как «address1», размер которого равен 100 (т. Е. Адрес varchar (100) null), и я передавал значение более 100 символов ... и это приводит к ошибке при сохранении данных в базе данных ....

Поэтому вы должны проверить данные, которые вы передаете в поле.


Чтобы быстро увидеть первую ошибку, даже не добавляя часы, вы можете вставить это в окно Immediate:

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

Это работает для меня.

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

Положите точку останова на оператор if. Затем вы можете проверить modelState в окне отладки. На каждое значение вы можете увидеть, есть ли ошибка и даже сообщение об ошибке. Вот и все. Когда вам это больше не нужно, просто удалите или прокомментируйте строку.

Я надеюсь, это поможет.

Если вас попросят, я могу предоставить подробный снимок экрана в окне отладки.


Я должен был написать это в окне Immediate: 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]

чтобы глубже вдаваться в точную ошибку!


просто проверьте длину поля таблицы базы данных. Текст ввода больше длины длины поля данных поля столбца





entity-framework-4.1