一个或多个实体的验证失败有关更多详细信息,请参见“ EntityValidationErrors”属性

浏览:42日期:2024-03-19
(adsbygoogle = window.adsbygoogle || []).push({}); 如何解决一个或多个实体的验证失败有关更多详细信息,请参见“ EntityValidationErrors”属性?

老实说,我不知道如何检查验证错误的内容。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在下面的评论中提供他的注释)。

对于在生产中并且使用 进行异常日志记录的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属性作为文本进行检查,而不必钻研验证集合,这有点尴尬,而且似乎并不适合所有人(请参见下面的评论)。

解决方法

使用代码优先方法为数据库播种时出现此错误。

一个或多个实体的验证失败。有关更多详细信息,请参见’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,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,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,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,ErrorMessage = 'Country should not be longer than 20 characters.')]public string Country { get; set; }[StringLength(20,ErrorMessage = 'City should not be longer than 20 characters.')]public string City { get; set; }[StringLength(50,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,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,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:UsersLUIS.SIMBIOSDocumentsVisual Studio 2010ProjectsSlnHRHRRazorFormsContentpictures1.jpg') }; Applicant john = new Applicant() {name = 'John',skypeuser = 'jo.valencia',telephone = '3435343543',photo = File.ReadAllBytes(@'C:UsersLUIS.SIMBIOSDocumentsVisual Studio 2010ProjectsSlnHRHRRazorFormsContentpictures2.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,StatusID = 1 }; context.ApplicantsPositions.Add(appicantposition);context.ApplicantsPositions.Add(appicantposition2); #endregion context.SaveChanges(); --->> Error here} }}

相关文章: