EF Code First:如何从nuget包控制台中看到“EntityValidationErrors”属性?

我对此感到不知所措:

我已经定义了我的类为一个entity framework(4.1.3)代码的第一种方法。 一切都很好(我正在创build表等),直到我开始种子。

现在当我做了

Add-Migration "remigrate" ; Update-Database; 

我在包控制台上得到一个错误“一个或多个实体的validation失败。有关更多详细信息,请参阅”EntityValidationErrors“属性。

我在我的Seed()方法中有一个断点,但是因为我在控制台上运行这个项目时没有运行,我很无知,如何去详细信息(PS – 我已经看到线程validation失败对于一个或多个实体,同时使用entity framework保存对SQL Server数据库的更改 ,显示如何查看该属性。)

我知道我的Seed()方法有一个问题,因为如果我在方法调用后立即返回,错误就会消失。 那么如何设置我的断点,以便我可以看到validation错误是什么? 有点失落了 还是有一些其他的方式来追踪它在nuget控制台?

我最近也被这个烦恼了。 我通过在Seed方法中的Configuration类中放置一个包装器函数来解决这个问题,并将调用replace为调用我的函数的SaveChanges 。 这个函数只需枚举EntityValidationErrors集合中的错误,并在Exception消息列出单个问题的地方重新引发exception。 这使得输出显示在NuGet包pipe理器控制台中。

代码如下:

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

只需在您的种子方法中将调用replace为context.SaveChanges()SaveChanges(context)

用部分类定义扩展您的DBContext类!

如果你看看你的DbContext的类定义,它将如下所示:

 // DatabaseContext.cs -- This file is auto generated and thus shouldn't be changed. public partial class [DatabaseContextName] : DbContext { ... } 

所以,在另一个文件中,你可以创build相同的定义,并覆盖你想要的部分。

 // partialDatabaseContext.cs -- you can safely make changes // that will not be overwritten in here. public partial class [DatabaseContextName] : DbContext { // Override defaults here } 

使用部分类的整个想法 – 你注意到DbContext是一个部分类 –就是你可以扩展一个已经生成的类(或者把类组织成多个文件),在我们的例子中,我们也想覆盖 SaveChanges方法从一个添加到DbContext的分类中

通过这种方式,我们可以从现有的所有DbContext / SaveChanges调用中获取错误debugging信息,而不必更改您的种子代码或开发代码。

这是我会做的( 注意不同的是,我只是在我们自己创作的DbContext部分类中重写SaveChanges方法,而不是生成的 )。 另外,确保你的部分课程使用了正确的名称空间,否则你将头撞墙。

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

我将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(); 

我将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()); } 

理查德感谢让我在正确的道路(同样的问题)下面是一个替代没有包装这在我的迁移configuration种子方法:

  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 

然后能够在包pipe理器控制台中看到exception。 希望这有助于某人。

 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