一个或多个实体的验证失败。有关更多详细信息,请参见“ 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
        }
    }
}

Answers:


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进行异常日志记录的Web应用程序,事实证明,这对于我创建自定义异常并进行覆盖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在Web界面或已发送的电子邮件(如果已配置)中显示的黄色错误屏幕现在直接在消息顶部显示验证详细信息。

  • Message在自定义异常中覆盖而不是覆盖属性ToString()的好处是,标准ASP.NET“黄色死亡屏幕(YSOD)”也显示此消息。与Elmah相反,YSOD显然不使用ToString(),但是两者都显示Message属性。

  • 将原始文件包装DbEntityValidationException为内部异常可确保原始堆栈跟踪仍然可用,并显示在Elmah和YSOD中。

  • 通过在行上设置一个断点,throw newException;您可以简单地将newException.Message属性作为文本进行检查,而不必钻研验证集合,这有点尴尬,而且似乎不适用于所有人(请参见下面的评论)。


87
钻探异常无济于事。它只是说有一个DbEntityValidationResult,但不允许您扩展!
Shumii 2012年

30
@Shumii请参阅此答案以扩展异常。
卡文·冯·戴伦

18
只是为了扩展一个优雅的解决方案。您可能想要覆盖自己的DbContext类中的savechanges方法,然后添加try catch块,其中try块只是尝试保存(base.SaveChanges()),而catch块仅捕获DbEntityValidationException。这样,您无需在保存更改的每个位置添加它。
米尔顿

7
这已经不止一次地节省了我的培根。我只能投票一次。希望它们使我每次复制和粘贴此内容时都可以投票。
达蒙·德雷克

5
代码为+2。的确是一个救星:) -1 Console.WriteLine,我估计现在有更多的人在编写Web项目,然后在控制台应用程序中Debug.Write工作,并且在这两者中都可以工作……
Bart 2014年

459

您可以在调试过程中通过Visual Studio进行操作,而无需编写任何代码,甚至不需要catch代码块。

只需添加名称如下的手表:

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

watch表达式$exception显示在当前上下文中引发的任何异常,即使尚未捕获并分配给变量也是如此。

基于http://mattrandle.me/viewing-entityvalidationerrors-in-visual-studio/


39
+1方式是更好的解决方案,并且不需要更改代码。酷
Justas 2014年

4
+1非常非常方便!您甚至都不需要try / catch块。只要在VS中断并瞧瞧时将其保留在监视列表中,您就可以看到验证错误。
theyetiman 2014年

40
一年两次,我都忘记了如何做并找到答案
贾斯汀·摩尔

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 2015年

2
我知道在评论中不欢迎“谢谢”,但是为了避免浪费我数小时的时间……谢谢!
路德

105

这实际上可以做到,而无需编写代码:

在您的catch块中,在以下代码行中添加一个断点:

catch (Exception exception)
{

}

现在,如果您将鼠标悬停exception或添加到Watch,然后导航到异常详细信息,如下所示;您将看到是哪个/哪些特定列引起了该问题,因为违反表约束时通常会发生此错误。

在此处输入图片说明

大图


4
这种方法非常简单,并利用了IDE :)
dsnunez,2015年

3
这是一个很好的解决方案,因为它快速,简单,可以使用IDE,并为我节省了大量时间。
maxshuty 2015年

2
我喜欢这样的方式:“如何成为一名编码者而不是编写代码”
免费开放

1
谢谢。这很简单,但是使用IDE查看异常真棒。
Thomas.Benz

完美的解决方案
Neeraj Singh Chouhan

46

这是您可以在Visual Studio中检查EntityValidationErrors内容的方法(无需编写任何额外的代码),即在IDE中进行调试时。

问题?

没错,Visual Studio调试器的“ 查看详细信息”弹出窗口不会在EntityValidationErrorscollection中显示实际错误。

在此处输入图片说明

解决方案!

只需在“ 快速监视”窗口中添加以下表达式,然后单击“ 重新评估”

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

以我为例,看看我如何能够扩展到集合ValidationErrors List内部EntityValidationErrors

在此处输入图片说明

参考: mattrandle.me博客文章@ yoel的答案


3
为什么这个问题没有解决?它应该显示错误而不是其他内容
Geomorillo

2
验证错误显示属性错误,例如。必填项,很好的答案,谢谢
hamzeh.hanandeh '18

1
大!它挽救了我的夜晚!:)
Patrick

1
这是可视化手表中确切错误的明智方法...谢谢!
Qwerty

39

快速查看第一个错误而无需添加手表的方法,可以将其粘贴到“即时窗口”中:

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

1
您也可以使用$ exception.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.ErrorMessage)来获取所有这些信息:)使用即时窗口的恕我直言是最好的答案
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属性无效时,它无效。

例如,假设您有一个Phone复杂类型的属性PhoneNumber。如果AreaCode属性无效,则属性名称ve.PropertyNames为“ Phone.AreaCode”。这将导致呼叫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());
    }
}

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

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中捕获异常,然后快速观察或按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”错误时,是.... i数据库“ tbladdress”中的数据库“ db1”中有一个字段为“ address1”,其大小为100(即地址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。在每个值上,您都可以查看是否存在错误,甚至错误消息。而已。当您不再需要它时,只需删除或注释该行。

我希望这将有所帮助。

如果需要,我可以在调试窗口中提供详细的屏幕截图。


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,并且由此,我的代码不会再出现此错误

因此,如果您使数据库的数据完整性无效,则可能会发生此错误


1
这里不是重点,是否应该提出例外。接下来,您要在这里偷工减料。当数据库模式中需要一个字段时,您需要的不仅仅是字段DbEntityValidationException
Gert Arnold

2

请检查您要传递的字段值,该值有效且与数据库字段一致。例如,在特定字段中传递的字符数少于在数据库表字段中定义的字符数。


1

如果您将IISWindows身份验证实体框架一起使用,请注意使用authorize

我尝试在POST没有授权的情况下无法正常工作,并且db.SaveChangesAsync();在所有其他动词GETDELETE都起作用时,在上收到此错误。

但是,当我添加AuthorizeAttribute作为注释时,它可以工作。

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

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

1

在我的情况下,这是因为数据库字段的长度小于输入字段的长度。

数据库表

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

我的输入

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

该值Username length5,其是lessthan6

...这可能对某人有帮助


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);
    }
  }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.