Проверка не удалась для одного или нескольких объектов. См. Свойство EntityValidationErrors для более подробной информации

804

У меня возникла эта ошибка при заполнении базы данных с использованием подхода «сначала код».

Проверка не удалась для одного или нескольких объектов. См. Свойство EntityValidationErrors для более подробной информации.

Честно говоря, я не знаю, как проверить содержание ошибок проверки. Visual Studio показывает, что это массив с 8 объектами, поэтому 8 ошибок проверки.

Это работало с моей предыдущей моделью, но я внес несколько изменений, которые я объясню ниже:

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

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

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

Slauma
источник
87
Бурение в исключение ничего не делает. Он просто говорит, что есть DbEntityValidationResult, но не позволяет вам расширяться !!
Шуми
30
@Shumii Смотрите этот ответ, чтобы расширить исключение.
Кавин ФонДейлен
18
Просто чтобы расширить элегантное решение. Вы можете переопределить метод savechanges в своем собственном классе DbContext, а затем добавить блок try catch, в котором блок try просто пытается сохранить (base.SaveChanges ()), а блок catch перехватывает только DbEntityValidationException. Таким образом, вам не нужно добавлять его в каждое место, где вы сохраняете свои изменения.
Милтон
7
Это спасло мой бекон не раз. Я мог только проголосовать один раз. Хотел, чтобы они давали мне голос за каждый раз, когда я копировал и вставлял это.
Дэймон Дрейк,
5
+2 за код. Действительно, спаситель :) -1 для использования Console.WriteLine, по моим оценкам, больше людей пишут веб-проекты, чем консольные приложения в настоящее время, и Debug.Writeработают в обоих ...
Барт
459

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

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

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

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

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

Йоэль Хэлб
источник
39
+1 Путь лучшее решение, и не требует изменений в коде. Круто
Юстас
4
+1 это очень и очень удобно! Вам даже не нужно иметь блок try / catch. Просто вставьте это в список наблюдения, когда VS сломается и вуаля .. у вас есть ошибки проверки перед вами.
пятый
40
пару раз в году я забываю, как это сделать, и нахожу этот ответ
Джастин Мур,
3
@zairja Я не проверял это на vb.net, но похоже, что переменная определена и для vb.net в msdn.microsoft.com/en-us/library/ms164891.aspx , однако приведение, вероятно, не определено для vb.net, и вместо этого вы, вероятно, должны сделать DirectCast ($ исключение, System.Data.Entity.Validation.DbEntityValidationException)
половина дня
2
Я знаю, что "спасибо" не приветствуются в комментариях, но ради того, чтобы не тратить на меня часы потраченного времени ... спасибо!
Лютер
105

Это действительно может сделать это без необходимости писать код:

В блоке catch добавьте точку останова в следующей строке кода:

catch (Exception exception)
{

}

Теперь, если вы наведите курсор мыши exceptionили добавите его в, Watchа затем перейдите к деталям исключения, как показано ниже; вы увидите, какие столбцы (столбцы) вызывают / вызывают проблему, поскольку эта ошибка обычно возникает при нарушении ограничения таблицы.

введите описание изображения здесь

Большое изображение

t_plusplus
источник
4
Этот подход очень прост и использует преимущества IDE :)
dsnunez
3
Это хорошее решение, потому что оно быстрое, простое, использует IDE и сэкономило мне массу времени.
максшуты
2
Мне нравится этот способ «Как быть программистом, а не писать код»
открыт и свободен
1
Спасибо. Это просто, но замечательно просматривать исключение с помощью IDE.
Thomas.Benz
идеальное решение
Neeraj Singh Chouhan
46

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

Проблема?

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

введите описание изображения здесь

Решение!

Просто добавьте следующее выражение в окне Quick Watch и нажмите Reevaluate .

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

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

введите описание изображения здесь

Ссылки: mattrandle.me блоге , @ Йоэль Ответим

Шива
источник
3
почему это не было исправлено? это должно показать ошибку, а не что-то другое
Geomorillo
2
Ошибка проверки показывает ошибку свойства, напр. поле обязательно для заполнения, хороший ответ, спасибо
hamzeh.hanandeh
1
Большой! Это спасло мою ночь! :)
Патрик
1
это умный способ визуализировать точную ошибку в часах ... спасибо!
Qwerty
39

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

((System.Data.Entity.Validation.DbEntityValidationException)$exception)
    .EntityValidationErrors.First()
    .ValidationErrors.First()
djdmbrwsk
источник
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
nghiavt
источник
12

Пока вы находитесь в режиме отладки внутри catch {...}блока, откройте окно «QuickWatch» ( ctrl+ alt+ q) и вставьте туда:

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

или:

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

Если вы не участвуете в программе try / catch или не имеете доступа к объекту исключения.

Это позволит вам углубиться в ValidationErrorsдерево. Я нашел самый простой способ получить мгновенное представление об этих ошибках.

GONeale
источник
10

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

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

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

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

Greg
источник
9

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

Хардип Сингх
источник
9

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

context.GetValidationErrors()
silverfox1948
источник
8

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

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

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

Ниже приведен FormattedDbEntityValidationExceptionкласс @ Slauma с поддержкой 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());
    }
}
mikesigs
источник
1
Я не могу поверить, что больше людей не проголосовали за это, поскольку это очень реальный сценарий, и он сводил меня с ума в последние две ночи. Вы знаете, что чувство, которое вы получаете, когда понимаете, что обработка ошибок - это то, что на самом деле вызывает ошибку? Тьфу.
DJ Grossman
7

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

Эрик Нельсон
источник
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);
    }
}
jocull
источник
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>
Phoenix_uy
источник
5

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

Brandon.Staley
источник
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;
        }
IfElseTryCatch
источник
5

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

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

Дхармендра Праджапати
источник
1
Я ценю этот ответ, потому что он действительно помог мне исправить мою ошибку. Таблица, в которую я сохранял свою базу данных, содержала все not nullстолбцы, поэтому, как только я добавил данные ко всем элементам до моего, db.SaveChanges()я не получил никакой ошибки.
BinaryJoe01
3

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

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

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

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

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

AngelDown
источник
3

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

 try
 {
  ....
 }
 catch(DbEntityValidationException ex)
 {
  ....
 }
Mayank
источник
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, и в этом случае мой код не выдаст мне эту ошибку снова

Так что эта ошибка может произойти, если вы лишите законной силы целостность своих данных

Башир Аль-Момани
источник
1
Вопрос о том, следует ли делать исключение, не имеет значения. Далее вы режете некоторые углы здесь. Когда поле требуется в схеме базы данных, вам нужно больше, чем для DbEntityValidationExceptionподнятия.
Герт Арнольд
2

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

Арун Тивари
источник
1

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

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

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

[Authorize]
public async Task<IHttpActionResult> Post(...){
....
}
Toodoo
источник
1

Вот еще один способ сделать это вместо использования циклов foreach для поиска внутри EntityValidationErrors. Конечно, вы можете отформатировать сообщение по своему вкусу:

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
источник
1

В моем случае это было из-за того, что длина поля базы данных меньше длины поля ввода.

таблица базы данных

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

Мой вклад

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

значение для Username lengthявляется 5 , который является lessthan6

... это может кому-то помочь

Qwerty
источник
1

Также боролся с этой ошибкой и основывался на теме здесь, и этот ответ смог выяснить фрагмент для копирования / вставки без необходимости выяснить, что должно быть импортировано (отлично для новичков в 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);
    }
  }
}
Даниэль Даниелецкий
источник
0

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

с Jagathish
источник
0

Я тоже столкнулся с той же проблемой. Я обновил свой .edmx из базы данных после того, как исключение исчезло.

HariChintha
источник
0

Эта ошибка возникает в основном из-за размера поля. ПРОВЕРЬТЕ все размеры полей в таблице базы данных.

Александр Залдостанов
источник