我为此感到茫然:
我已经为实体框架(4.1.3)代码第一种方法定义了我的类。一切都很好(我正在制作桌子等),直到我开始播种。
现在我做
Add-Migration "remigrate" ; Update-Database;
我在程序包控制台上收到错误“一个或多个实体的验证失败。有关详细信息,请参阅'EntityValidationErrors'属性。”
我的Seed()方法中有一个断点但是因为我在项目没有运行时在控制台上运行它,所以我对如何获取细节一无所知(PS - 我见过线程Validation failed for one or more entities while saving changes to SQL Server Database using Entity Framework,显示我如何看到该属性。)
我知道我的Seed()方法有问题,因为如果我在方法调用后立即返回,则错误就会消失。那么如何设置断点以便我可以看到验证错误是什么?有点失落。或者是否有其他方法可以在nuget控制台中跟踪它?
答案 0 :(得分:212)
我最近也对此感到恼火。我通过在Seed方法的Configuration类中放置一个包装器函数来修复它,并通过调用我的函数来替换对SaveChanges
的调用。此函数将简单地枚举EntityValidationErrors
集合中的错误,并重新抛出异常消息列出各个问题的异常。这使得输出显示在NuGet包管理器控制台中。
代码如下:
/// <summary>
/// Wrapper for SaveChanges adding the Validation Messages to the generated exception
/// </summary>
/// <param name="context">The context.</param>
private void SaveChanges(DbContext context) {
try {
context.SaveChanges();
} catch (DbEntityValidationException ex) {
StringBuilder sb = new StringBuilder();
foreach (var failure in ex.EntityValidationErrors) {
sb.AppendFormat("{0} failed validation\n", failure.Entry.Entity.GetType());
foreach (var error in failure.ValidationErrors) {
sb.AppendFormat("- {0} : {1}", error.PropertyName, error.ErrorMessage);
sb.AppendLine();
}
}
throw new DbEntityValidationException(
"Entity Validation Failed - errors follow:\n" +
sb.ToString(), ex
); // Add the original exception as the innerException
}
}
只需在种子方法中用context.SaveChanges()
替换SaveChanges(context)
的来电。
答案 1 :(得分:110)
已使用部分类定义扩展您的DBContext类!
如果查看DbContext的类定义,它将类似于以下内容:
// DatabaseContext.cs -- This file is auto generated and thus shouldn't be changed.
public partial class [DatabaseContextName] : DbContext { ... }
因此,在另一个文件中,您可以创建相同的定义并覆盖您想要的部分。
// partialDatabaseContext.cs -- you can safely make changes
// that will not be overwritten in here.
public partial class [DatabaseContextName] : DbContext { // Override defaults here }
部分类的整个想法 - 您是否注意到 DbContext 是一个部分类 - 是您可以扩展已生成(或组织)的类我们还希望在添加到 DbContext 的分部类中覆盖 SaveChanges 方法。
这样我们可以从所有现有的DbContext / SaveChanges调用中获取错误调试信息,而不必更改种子代码或开发代码。
这就是我要做的事情(注意不同之处在于我只是在我们自己编写的 DbContext 部分类中重写了SaveChanges方法, NOT THE GENERATED ONE )。此外,请确保您的部分课程使用正确的命名空间,否则您将会碰壁。
public partial class Database : DbContext
{
public override int SaveChanges()
{
try
{
return base.SaveChanges();
}
catch (DbEntityValidationException ex)
{
var sb = new StringBuilder();
foreach (var failure in ex.EntityValidationErrors)
{
sb.AppendFormat("{0} failed validation\n", failure.Entry.Entity.GetType());
foreach (var error in failure.ValidationErrors)
{
sb.AppendFormat("- {0} : {1}", error.PropertyName, error.ErrorMessage);
sb.AppendLine();
}
}
throw new DbEntityValidationException(
"Entity Validation Failed - errors follow:\n" +
sb.ToString(), ex
); // Add the original exception as the innerException
}
}
}
答案 2 :(得分:35)
我将Richards的答案转换为扩展方法:
public static int SaveChangesWithErrors(this DbContext context)
{
try
{
return context.SaveChanges();
}
catch (DbEntityValidationException ex)
{
StringBuilder sb = new StringBuilder();
foreach (var failure in ex.EntityValidationErrors)
{
sb.AppendFormat("{0} failed validation\n", failure.Entry.Entity.GetType());
foreach (var error in failure.ValidationErrors)
{
sb.AppendFormat("- {0} : {1}", error.PropertyName, error.ErrorMessage);
sb.AppendLine();
}
}
throw new DbEntityValidationException(
"Entity Validation Failed - errors follow:\n" +
sb.ToString(), ex
); // Add the original exception as the innerException
}
}
这样打电话:
context.SaveChangesWithErrors();
答案 3 :(得分:4)
我将craigvl的版本转换为C#我必须添加context.SaveChanges();为了让它对我有用,如下所示。
try
{
byte[] bytes = System.IO.File.ReadAllBytes(@"C:\Users\sheph_000\Desktop\Rawr.png");
Console.WriteLine(bytes);
context.BeverageTypes.AddOrUpdate(
x => x.Name,
new AATPos.DAL.Entities.BeverageType { ID = 1, Name = "Sodas" }
);
context.Beverages.AddOrUpdate(
x => x.Name,
new AATPos.DAL.Entities.Beverage { ID = 1, Name = "Coke", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" },
new AATPos.DAL.Entities.Beverage { ID = 2, Name = "Fanta", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" },
new AATPos.DAL.Entities.Beverage { ID = 3, Name = "Sprite", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" },
new AATPos.DAL.Entities.Beverage { ID = 4, Name = "Cream Soda", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" },
new AATPos.DAL.Entities.Beverage { ID = 5, Name = "Pepsi", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" }
);
context.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException ex)
{
var sb = new System.Text.StringBuilder();
foreach (var failure in ex.EntityValidationErrors)
{
sb.AppendFormat("{0} failed validation", failure.Entry.Entity.GetType());
foreach (var error in failure.ValidationErrors)
{
sb.AppendFormat("- {0} : {1}", error.PropertyName, error.ErrorMessage);
sb.AppendLine();
}
}
throw new Exception(sb.ToString());
}
答案 4 :(得分:3)
理查德感谢让我走上正确的道路(有同样的问题)下面是一个替代方案,没有在迁移配置种子方法中为我工作的包装器:
Protected Overrides Sub Seed(context As NotificationContext)
Try
context.System.AddOrUpdate(
Function(c) c.SystemName,
New E_NotificationSystem() With {.SystemName = "System1"},
New E_NotificationSystem() With {.SystemName = "System2"},
New E_NotificationSystem() With {.SystemName = "System3"})
context.SaveChanges()
Catch ex As DbEntityValidationException
Dim sb As New StringBuilder
For Each failure In ex.EntityValidationErrors
sb.AppendFormat("{0} failed validation" & vbLf, failure.Entry.Entity.[GetType]())
For Each [error] In failure.ValidationErrors
sb.AppendFormat("- {0} : {1}", [error].PropertyName, [error].ErrorMessage)
sb.AppendLine()
Next
Next
Throw New Exception(sb.ToString())
End Try
End Sub
然后能够在包管理器控制台中看到异常。希望这有助于某人。
答案 5 :(得分:0)
I Also had same model validation problem but successfully catch by myself after lot of thinking;
I use reverse engineering method to catch the problem out of Over 80 + Model Classes;
1> Made copy of dbcontext, changing the name (I add "1" at end and make respective changes in class constructor and initialization etc.
Old:
>public class AppDb : IdentityDbContext<ApplicationUser>
>
> {
> public AppDb(): base("DefaultConnection", throwIfV1Schema: false)
> {
>
> }
>
> public static AppDb Create()
>{
>return new AppDb();
>}
**New:**
>public class AppDb1 : IdentityDbContext<ApplicationUser>
>{
>public AppDb1()
>: base("DefaultConnection", throwIfV1Schema: false)
>{
>}
>
>public static AppDb1 Create()
> {
> return new AppDb1();
> }`
...
2> Make changes to Codefirst Migration Configuration from Old DbContext to my new Context.
> internal sealed class Configuration :
> DbMigrationsConfiguration<DAL.AppDb1> { public Configuration() {
> AutomaticMigrationsEnabled = false; } protected override void
> Seed(DAL.AppDb1 context) {`
3> Comment the Dbsets in new DbContext which was doubt.
4> Apply update migration if succeeded the probelm lye in Commented section.
5> if not then commented section is clear of bug clear.
6> repeat the (4) until found the right place of bug.
7> Happy Codding
&#13;