一个或多个实体的验证失败。请参阅“EntityValidationErrors”属性了解更多详情

发布于 2024-12-10 01:52:06 字数 9231 浏览 1 评论 0原文

我在使用代码优先方法为数据库播种时遇到此错误。

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

I am having this error when seeding my database with code first approach.

Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.

To be honest I don't know how to check the content of the validation errors. Visual Studio shows me that it's an array with 8 objects, so 8 validation errors.

This was working with my previous model, but I made a few changes that I explain below:

  • I had an enum called Status, I changed it to a class called Status
  • I changed the class ApplicantsPositionHistory to have 2 foreign key to the same table

Excuse me for the long code, but I have to paste it all. The exception is thrown in the last line of the following code.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(29

执妄 2024-12-17 01:52:07

在调试中,您可以在 QuickWatch 表达式计算器输入字段中输入以下内容:

context.GetValidationErrors()

In debug, you can enter this in your QuickWatch expression evaluator entry field:

context.GetValidationErrors()
贱贱哒 2024-12-17 01:52:07

也在努力解决这个错误,并根据此处的主题,这个答案能够找出要复制/粘贴的片段,而无需要弄清楚必须导入什么(对于 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);
    }
  }
}

Was also struggling with this error and based on the topic here and this answer was able to figure out snippet to copy/paste without the need to figure out what has to be imported (excellent for C# beginners), code below:

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);
    }
  }
}
秋意浓 2024-12-17 01:52:07

请注意,Entity.GetType().BaseType.Name 给出您指定的类型名称,而不是名称中包含所有十六进制数字的类型名称。

Note that Entity.GetType().BaseType.Name gives the type name you specified, not the one with all the hex digits in its name.

二手情话 2024-12-17 01:52:07

我必须在立即窗口中写下这个: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]

才能深入了解确切的错误!

编辑:
显然,有一个更短、更好的版本可以获取所有错误,而不仅仅是第一个错误:

$exception.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.ErrorMessage)

I had to write this in the Immediate window :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]

in order to get deep into the exact error !

EDIT:
Apparently there is a shorter and better version to get all errors, not just the first:

$exception.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.ErrorMessage)

丢了幸福的猪 2024-12-17 01:52:07

根据 @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);
    }
}

Per @Slauma's answer and @Milton's suggestion I've extended our base class's custom save method with a try/catch that will handle (and hence log in our error logging!) these sorts of exceptions.

// 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);
    }
}
带刺的爱情 2024-12-17 01:52:07

使用@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>

Using the answer of @Slauma i have made a code snippet (a surrounds with snippet) for better use.

<?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>
浮生未歇 2024-12-17 01:52:07

在 try catch 中捕获异常,然后快速监视或 ctrl+d & ctrl+q,您可以深入查看 EntityValidationErrors。

Catch the exception in a try catch and then quick watch or ctrl+d & ctrl+q and you can drill down to the EntityValidationErrors.

雅心素梦 2024-12-17 01:52:07

只是投入我的两分钱......

在我的 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;
        }

Just throwing my two cents in...

Within my dbConfiguration.cs, I like to wrap my context.SaveChanges() method into a try/catch and produce an output text file that allows me to read the Error(s) clearly, and this code also timestamps them - handy if you run into more than one error at different times!

        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;
        }
可是我不能没有你 2024-12-17 01:52:07

我发现......当我收到“EntityValidationErrors”错误时......我在表“tbladdress”中的数据库“db1”中有一个字段为“address1”,其大小为100(即地址varchar(100) null) 并且我传递的值超过 100 个字符..这会导致在将数据保存到数据库时出错....

因此您必须检查传递到该字段的数据。

What i found...when i got 'EntityValidationErrors' error is that....i have a field in my database 'db1' in table 'tbladdress' as 'address1' which has size of 100 (i.e address varchar(100) null) and i was passing value more than 100 characters..and this leading to error while saving data to database....

So you must Check the data you are passing to the field.

我喜欢麦丽素 2024-12-17 01:52:07

这对我有用。

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

在 if 语句上放置断点。
然后您可以在调试窗口中检查 modelState。对于每个值,您都可以看到是否有错误,甚至是错误消息。就是这样。
当您不再需要它时,只需删除或注释该行即可。

我希望这会有所帮助。

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

This works for me.

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

Put a breakpoint on if statement.
Then you can check modelState in debug windows. On every value you can see if there is an error and even the error message. That's it.
When you don't need it anymore, just delete or comment the line.

I hope this will help.

If asked, I can provide detailed screenshot in the debug window.

べ映画 2024-12-17 01:52:07

正如其他帖子中提到的,只需捕获 DbEntityValidationException 类中的异常即可。
这将为您提供错误情况下所需的水。

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

As mentioned in other posts, simply catch the exception in DbEntityValidationException class.
Which will give you watever you required during error cases.

 try
 {
  ....
 }
 catch(DbEntityValidationException ex)
 {
  ....
 }
固执像三岁 2024-12-17 01:52:07

这是另一种方法,而不是使用 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;
    }

Here's another way to do it instead of using foreach loops for looking inside EntityValidationErrors. Of course you can format the message to your own liking :

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;
    }
森罗 2024-12-17 01:52:07

就我而言,这是因为数据库字段的长度小于输入字段的长度。

数据库表

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

我的输入

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

用户名 长度的值为5,即小于 6

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

In my case it was because of the length of the database field is less than the length of the input field.

database table

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

My input

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

the value for Username length is 5 which is lessthan 6

...this may help someone

千秋岁 2024-12-17 01:52:07

我遇到了此错误

当我尝试 更新我的特定字段时, 实体框架中的模型

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 有其引发的权利

,根据这个字段,我希望它可以为空,(我不知道我是如何搞砸的),

所以我更改了该字段以允许空,由此我的代码不会再给我这个错误

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

I faced this error before

when I tried to update specific field in my model in entity framwork

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

and according the above answers

I found the Validation message The SignerName field is required.

which pointing to field in my model

and when I checked my database schema I found

enter image description here

so off coure ValidationException has its right to raise

and according to this field I want it to be nullable, (I dont know how I messed it)

so I changed that field to allow Null, and by this my code will not give me this error again

so This error maybe will happened if you invalidate Your Data integrity of your database

调妓 2024-12-17 01:52:07

请检查您传递的字段值是否有效且符合数据库字段。例如,在特定字段中传递的字符数少于数据库表字段中定义的字符数。

Please check the fields value you are passing, are valid and according to database fields. For example number of characters passed in a particular field are less than the characters defined in database table field.

梦罢 2024-12-17 01:52:07

如果您将IISWindows 身份验证实体框架结合使用,请小心使用授权

我尝试在未经授权的情况下POST,但它不起作用,并在db.SaveChangesAsync();上收到此错误,而所有其他动词GET > 和 DELETE 正在工作。

但是当我添加 AuthorizeAttribute 作为注释时,它起作用了。

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

If you're using IIS with Windows Authentification and Entity Framework, be careful to use authorize.

I tried to POST without authorize and it didn't work, and get this error on db.SaveChangesAsync();, while all other verbs GET and DELETE were working.

But when I added AuthorizeAttribute as annotation, it worked.

[Authorize]
public async Task<IHttpActionResult> Post(...){
....
}
别忘他 2024-12-17 01:52:07

出现此错误的主要原因是字段大小。
检查数据库表中的所有字段大小。

This error occurs mostly because of field size.
CHECK all the field sizes in a database table.

我ぃ本無心為│何有愛 2024-12-17 01:52:07

检查表列中是否有 Not Null 约束,并且在插入/更新操作时未传递该列的值。
这会导致实体框架中出现此异常。

Check whether you have Not Null constraint in your table columns and you are not passes the value for that column while insert/Update operations.
That Causes this exception in entity framework.

想你的星星会说话 2024-12-17 01:52:07

我也面临同样的问题。异常消失后,我从数据库更新了 .edmx。

I also faced the same problem. I updated my .edmx from the database after that the exception has vanished.

ぶ宁プ宁ぶ 2024-12-17 01:52:06

说实话我不知道如何检查验证错误的内容。 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 属性,而不是深入到验证集合中,这有点麻烦尴尬,并且似乎对每个人来说都不容易工作(请参阅下面的评论)。

To be honest I don't know how to check the content of the validation errors. Visual Studio shows me that it's an array with 8 objects, so 8 validation errors.

Actually you should see the errors if you drill into that array in Visual studio during debug. But you can also catch the exception and then write out the errors to some logging store or the console:

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 is a collection which represents the entities which couldn't be validated successfully, and the inner collection ValidationErrors per entity is a list of errors on property level.

These validation messages are usually helpful enough to find the source of the problem.

Edit

A few slight improvements:

The value of the offending property can be included in the inner loop like so:

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

While debugging Debug.Write might be preferable over Console.WriteLine as it works in all kind of applications, not only console applications (thanks to @Bart for his note in the comments below).

For web applications that are in production and that use Elmah for exception logging it turned out to be very useful for me to create a custom exception and overwrite SaveChanges in order to throw this new exception.

The custom exception type looks like this:

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

And SaveChanges can be overwritten the following way:

public class MyContext : DbContext
{
    // ...

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

A few remarks:

  • The yellow error screen that Elmah shows in the web interface or in the sent emails (if you have configured that) now displays the validation details directly at the top of the message.

  • Overwriting the Message property in the custom exception instead of overwriting ToString() has the benefit that the standard ASP.NET "Yellow screen of death (YSOD)" displays this message as well. In contrast to Elmah the YSOD apparently doesn't use ToString(), but both display the Message property.

  • Wrapping the original DbEntityValidationException as inner exception ensures that the original stack trace will still be available and is displayed in Elmah and the YSOD.

  • By setting a breakpoint on the line throw newException; you can simply inspect the newException.Message property as a text instead of drilling into the validation collections which is a bit awkward and doesn't seem to work easily for everyone (see comments below).

向日葵 2024-12-17 01:52:06

您可以在调试期间从 Visual Studio 执行此操作,无需编写任何代码,甚至无需编写 catch 块。

只需添加一个名为以下的监视:

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

监视表达式 $exception 显示当前上下文中抛出的任何异常,即使该异常尚未被捕获并分配给变量。

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

You can do it from Visual Studio during debugging without writing any code, not even a catch block.

Just add a watch with the name:

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

The watch expression $exception displays any exception thrown in the current context, even if it has not been caught and assigned to a variable.

Based on http://mattrandle.me/viewing-entityvalidationerrors-in-visual-studio/

寄人书 2024-12-17 01:52:06

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

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

catch (Exception exception)
{

}

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

在此处输入图像描述

大图像

This could actually do it without having to write code:

In your catch block, add a break point at the following line of code:

catch (Exception exception)
{

}

Now if you hover on exception or add it to the Watch and then navigate into the exception details as shown below; you will see which particular column(s) is/ are causing the problem as this error usually occurs when a table-constraint is violated..

enter image description here

Large image

转角预定愛 2024-12-17 01:52:06

下面介绍了如何在 Visual Studio 中检查 EntityValidationErrors 的内容(无需编写任何额外代码),即在 IDE 中进行调试期间。

问题?

您是对的,Visual Studio 调试器的查看详细信息弹出窗口不会显示 EntityValidationErrors 集合中的实际错误。

输入图像描述这里

解决方案!

只需在快速观察窗口中添加以下表达式,然后单击重新评估即可。

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

在我的例子中,看看我如何能够扩展到 ValidationErrors List< EntityValidationErrors 集合中的 /code>

在此处输入图像描述

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

Here's how you can check the contents of the EntityValidationErrors in Visual Studio (without writing any extra code) i.e. during Debugging in the IDE.

The Problem?

You are right, the Visual Studio debugger's View Details Popup doesn't show the actual errors inside the EntityValidationErrors collection .

enter image description here

The Solution!

Just add the following expression in a Quick Watch window and click Reevaluate.

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

In my case, see how I am able to expand into the ValidationErrors List inside the EntityValidationErrors collection

enter image description here

References: mattrandle.me blog post, @yoel's answer

非要怀念 2024-12-17 01:52:06

要快速查看第一个错误,甚至无需添加手表,您可以将其粘贴到“立即窗口”中:

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

For a quick way to see the first error without even adding a watch you can paste this in the Immediate Window:

((System.Data.Entity.Validation.DbEntityValidationException)$exception)
    .EntityValidationErrors.First()
    .ValidationErrors.First()
情绪操控生活 2024-12-17 01:52:06

对于任何使用 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

For anyone who works in 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
你列表最软的妹 2024-12-17 01:52:06

当您在 catch {...} 块中处于调试模式时,打开“QuickWatch”窗口 (ctrl+alt+q) 并粘贴到其中:

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

或:

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

如果您未处于 try/catch 中或无权访问异常对象。

这将允许您深入查看 ValidationErrors 树。这是我发现的立即了解这些错误的最简单方法。

While you are in debug mode within the catch {...} block open up the "QuickWatch" window (ctrl+alt+q) and paste in there:

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

or:

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

If you are not in a try/catch or don't have access to the exception object.

This will allow you to drill down into the ValidationErrors tree. It's the easiest way I've found to get instant insight into these errors.

小霸王臭丫头 2024-12-17 01:52:06

如果您只是捕获一般异常,则将其转换为 DbEntityValidationException 可能会对您有利。这种类型的异常有一个 Validation Errors 属性,继续扩展到它们中,你会发现所有的问题。

例如,如果您在 catch 中放置断点,则可以将以下内容放入监视中:

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

错误的示例是 如果字段不允许空值,并且您有一个空字符串,您将看到它说该字段是必需的。

If you are simply catching a generic exception, it may benefit you to cast this as a DbEntityValidationException. This type of an exception has a Validation Errors property, and continuing to expand your way into them, you will find all the problems.

For example, if you put a break point in the catch, you can throw the following into a watch:

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

An example of an error is if a field does not allow nulls, and you have a null string, you'll see it say that the field is required.

随梦而飞# 2024-12-17 01:52:06

只需检查您的数据库表字段长度。
您的输入文本大于列字段数据类型长度的长度

just Check Your Database Table Field Length .
Your Input Text Is Greater than the length of column field data type length

围归者 2024-12-17 01:52:06

@Slauma 的答案确实很棒,但我发现当 ComplexType 属性无效时它不起作用。

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

The answer from @Slauma is really great but I found that it didnt't work when a ComplexType property was invalid.

For example, say you have a property Phone of the complex type PhoneNumber. If the AreaCode property is invalid, the property name in ve.PropertyNames is "Phone.AreaCode". This causes the call to eve.Entry.CurrentValues<object>(ve.PropertyName) to fail.

To fix this, you can split the property name at each ., then recurse through the resulting array of property names. Finally, when you arrive at the bottom of the chain, you can simply return the value of the property.

Below is @Slauma's FormattedDbEntityValidationException class with support for ComplexTypes.

Enjoy!

[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());
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文