我为此不知所措:
我已经为实体框架(4.1.3)代码优先方法定义了我的类。一切都很好(我正在创建表格等),直到我开始播种。
现在当我做
Add-Migration "remigrate" ; Update-Database;
我在包控制台上收到错误消息“一个或多个实体的验证失败。有关详细信息,请参阅 'EntityValidationErrors' 属性。”
我的 Seed() 方法中有一个断点,但是因为我在项目未运行时在控制台上运行它,所以我不知道如何获取详细信息(PS - 我已经看到了线程 {1 } 这显示了我如何看到该属性。)
我知道我的 Seed() 方法有问题,因为如果我在方法调用之后立即返回,错误就会消失。那么如何设置断点以便查看验证错误是什么?有点输了还是有其他方法可以在 nuget 控制台中跟踪它?
我最近也被这个惹恼了。我通过在 Seed 方法的 Configuration 类中放置一个包装函数来修复它,并将对 SaveChanges
的调用替换为对我的函数的调用。此函数将简单地枚举 EntityValidationErrors
集合中的错误,并在 Exception 消息列出各个问题时重新引发异常。这使得输出显示在 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)
。
已经使用部分类定义扩展您的 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 是一个部分类——是你可以扩展一个已经生成的类(或将类组织到多个文件中),在我们的例子中,我们还想覆盖 SaveChanges 方法从添加到 DbContext 的部分类中。
通过这种方式,我们可以从所有现有的 DbContext/SaveChanges 调用中获取错误调试信息,而无需更改您的种子代码或开发代码。
这就是我要做的(注意不同之处在于我只是在我们自己编写的 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
}
}
}
我将理查兹的答案转换为扩展方法:
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());
}
理查德感谢您让我走上正确的道路(有同样的问题),下面是一个没有包装器的替代方案,这在迁移配置种子方法中对我有用:
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
然后能够在包管理器控制台中看到异常。希望这可以帮助某人。
我也有同样的模型验证问题,但经过深思熟虑后自己成功地抓住了;我使用逆向工程方法从 80 多个模型类中找出问题; 1>复制dbcontext,更改名称(我在末尾添加“1”并在类构造函数和初始化等中进行相应更改。旧:>public class AppDb:IdentityDbContext
public override int SaveChanges()
在上下文中。