一个或多个实体的验证失败。请参阅“EntityValidationErrors”属性了解更多详情
我在使用代码优先方法为数据库播种时遇到此错误。
一个或多个实体的验证失败。有关更多详细信息,请参阅“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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(29)
在调试中,您可以在 QuickWatch 表达式计算器输入字段中输入以下内容:
In debug, you can enter this in your QuickWatch expression evaluator entry field:
也在努力解决这个错误,并根据此处的主题,这个答案能够找出要复制/粘贴的片段,而无需要弄清楚必须导入什么(对于 C# 初学者来说非常有用),代码如下:
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:
请注意,
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.我必须在立即窗口中写下这个:3
才能深入了解确切的错误!
编辑:
显然,有一个更短、更好的版本可以获取所有错误,而不仅仅是第一个错误:
$exception.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.ErrorMessage)
I had to write this in the Immediate window :3
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)
根据 @Slauma 的回答和 @Milton 的建议,我已经使用 try/catch 扩展了我们的基类的自定义保存方法,它将处理(并因此记录我们的错误日志记录!)这些类型的异常。
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.
使用@Slauma的答案,我制作了一个代码片段(带有片段的包围)以便更好地使用。
Using the answer of @Slauma i have made a code snippet (a surrounds with snippet) for better use.
在 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.
只是投入我的两分钱......
在我的 dbConfiguration.cs 中,我喜欢将 context.SaveChanges() 方法包装到 try/catch 中并生成一个输出文本文件,该文件允许我清楚地读取错误,并且这段代码还为它们添加了时间戳——如果您在不同时间遇到多个错误,这会很方便!
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!
我发现......当我收到“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.
这对我有用。
在 if 语句上放置断点。
然后您可以在调试窗口中检查 modelState。对于每个值,您都可以看到是否有错误,甚至是错误消息。就是这样。
当您不再需要它时,只需删除或注释该行即可。
我希望这会有所帮助。
如果询问,我可以在调试窗口中提供详细的屏幕截图。
This works for me.
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.
正如其他帖子中提到的,只需捕获 DbEntityValidationException 类中的异常即可。
这将为您提供错误情况下所需的水。
As mentioned in other posts, simply catch the exception in DbEntityValidationException class.
Which will give you watever you required during error cases.
这是另一种方法,而不是使用 foreach 循环来查看 EntityValidationErrors 内部。当然,您可以根据自己的喜好格式化消息:
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 :
就我而言,这是因为数据库字段的长度小于输入字段的长度。
数据库表
我的输入
用户名
长度
的值为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
My input
the value for
Username
length
is 5 which islessthan
6...this may help someone
我遇到了此错误
当我尝试 更新我的特定字段时, 实体框架中的模型
,根据上面的答案,
我找到了验证消息
The SignerName field is required.
,它指向我的模型中的字段
,当我检查数据库架构时,我发现
所以,
ValidationException
有其引发的权利,根据这个字段,我希望它可以为空,(我不知道我是如何搞砸的),
所以我更改了该字段以允许空,由此我的代码不会再给我这个错误
I faced this error before
when I tried to update specific field in my model in entity framwork
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
so off coure
ValidationException
has its right to raiseand 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
请检查您传递的字段值是否有效且符合数据库字段。例如,在特定字段中传递的字符数少于数据库表字段中定义的字符数。
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.
如果您将IIS与Windows 身份验证和实体框架结合使用,请小心使用
授权
。我尝试在未经授权的情况下
POST
,但它不起作用,并在db.SaveChangesAsync();
上收到此错误,而所有其他动词GET
> 和DELETE
正在工作。但是当我添加 AuthorizeAttribute 作为注释时,它起作用了。
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 ondb.SaveChangesAsync();
, while all other verbsGET
andDELETE
were working.But when I added AuthorizeAttribute as annotation, it worked.
出现此错误的主要原因是字段大小。
检查数据库表中的所有字段大小。
This error occurs mostly because of field size.
CHECK all the field sizes in a database table.
检查表列中是否有
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.
我也面临同样的问题。异常消失后,我从数据库更新了 .edmx。
I also faced the same problem. I updated my .edmx from the database after that the exception has vanished.
实际上,如果在调试期间在 Visual Studio 中深入查看该数组,您应该会看到错误。但您也可以捕获异常,然后将错误写入某些日志存储或控制台:
EntityValidationErrors
是一个集合,表示无法成功验证的实体,内部集合ValidationErrors 是属性级别的错误列表。
这些验证消息通常足以帮助找到问题的根源。
编辑
一些细微的改进:
有问题的属性的值可以包含在内部循环中,如下所示:
调试时
Debug.Write
可能是优于Console.WriteLine,因为它适用于所有类型的应用程序,而不仅仅是控制台应用程序(感谢@Bart在下面的评论中的注释)。对于正在生产中并且使用 Elmah 进行异常日志记录的 Web 应用程序来说,创建自定义异常并覆盖
SaveChanges
以便抛出此异常对我来说非常有用新的异常。自定义异常类型如下所示:
并且
SaveChanges
可以通过以下方式覆盖:一些备注:
Elmah 在 Web 界面或发送的电子邮件中显示的黄色错误屏幕(如果您已配置)现在直接在消息顶部显示验证详细信息。
覆盖自定义异常中的
Message
属性而不是覆盖ToString()
的好处是显示标准 ASP.NET“黄屏死机 (YSOD)”这条消息也是如此。与 Elmah 相比,YSOD 显然不使用ToString()
,但两者都显示Message
属性。将原始
DbEntityValidationException
包装为内部异常可确保原始堆栈跟踪仍然可用并显示在 Elmah 和 YSOD 中。通过在
throw newException;
行上设置断点,您可以简单地以文本形式检查newException.Message
属性,而不是深入到验证集合中,这有点麻烦尴尬,并且似乎对每个人来说都不容易工作(请参阅下面的评论)。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:
EntityValidationErrors
is a collection which represents the entities which couldn't be validated successfully, and the inner collectionValidationErrors
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:
While debugging
Debug.Write
might be preferable overConsole.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:
And
SaveChanges
can be overwritten the following way: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 overwritingToString()
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 useToString()
, but both display theMessage
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 thenewException.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).您可以在调试期间从 Visual Studio 执行此操作,无需编写任何代码,甚至无需编写 catch 块。
只需添加一个名为以下的监视:
监视表达式
$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:
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/
这实际上可以做到这一点,而无需编写代码:
在您的 catch 块中,在以下代码行中添加一个断点:
现在,如果您将鼠标悬停在
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:
Now if you hover on
exception
or add it to theWatch
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..Large image
下面介绍了如何在 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 .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 theEntityValidationErrors
collectionReferences: mattrandle.me blog post, @yoel's answer
要快速查看第一个错误,甚至无需添加手表,您可以将其粘贴到“立即窗口”中:
For a quick way to see the first error without even adding a watch you can paste this in the Immediate Window:
对于任何使用
VB.NET
工作的人For anyone who works in
VB.NET
当您在
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.如果您只是捕获一般异常,则将其转换为 DbEntityValidationException 可能会对您有利。这种类型的异常有一个 Validation Errors 属性,继续扩展到它们中,你会发现所有的问题。
例如,如果您在 catch 中放置断点,则可以将以下内容放入监视中:
错误的示例是 如果字段不允许空值,并且您有一个空字符串,您将看到它说该字段是必需的。
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:
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.
只需检查您的数据库表字段长度。
您的输入文本大于列字段数据类型长度的长度
just Check Your Database Table Field Length .
Your Input Text Is Greater than the length of column field data type length
@Slauma 的答案确实很棒,但我发现当 ComplexType 属性无效时它不起作用。
例如,假设您有一个复杂类型
PhoneNumber
的属性Phone
。如果AreaCode
属性无效,则ve.PropertyNames
中的属性名称为“Phone.AreaCode”。这会导致对eve.Entry.CurrentValues
要解决此问题,您可以在每个
.
处拆分属性名称,然后递归遍历生成的属性名称数组。最后,当到达链的底部时,您可以简单地返回属性的值。下面是 @Slauma 的
FormattedDbEntityValidationException
类,支持 ComplexTypes。享受!
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 typePhoneNumber
. If theAreaCode
property is invalid, the property name inve.PropertyNames
is "Phone.AreaCode". This causes the call toeve.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!