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

jer*_*emy 124 entity-framework entity-framework-4 nuget asp.net-mvc-3

我为此感到茫然:

我已经为实体框架(4.1.3)代码第一种方法定义了我的类.一切都很好(我正在制作桌子等),直到我开始播种.

现在当我这样做的时候

Add-Migration "remigrate" ; Update-Database;
Run Code Online (Sandbox Code Playgroud)

我在程序包控制台上收到错误"一个或多个实体的验证失败.有关详细信息,请参阅'EntityValidationErrors'属性."

我的Seed()方法中有一个断点但是因为我在项目没有运行时在控制台上运行它,我对如何获取细节毫无头绪(PS - 我看过线程验证失败对于一个或多个实体,同时使用Entity Framework保存对SQL Server数据库的更改,实体框架显示了我如何查看属性.)

我知道我的Seed()方法有问题,因为如果我在方法调用之后立即返回,则错误消失.那么如何设置断点以便我可以看到验证错误是什么?有点失落.或者是否有其他方法可以在nuget控制台中跟踪它?

Ric*_*ard 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
    }
}
Run Code Online (Sandbox Code Playgroud)

只需在种子方法中替换对context.SaveChanges()with的调用SaveChanges(context).

  • 使用部分类更有效,我在下面已经回答过. (5认同)
  • 我使用了这种技术,但在上下文中使用了覆盖savechanges.`public override int SaveChanges()`在上下文中. (3认同)
  • 工作出色 - 感谢您的解决方案. (2认同)

jwi*_*ize 113

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

如果您查看DbContext的类定义,它将类似于以下内容:

// DatabaseContext.cs   -- This file is auto generated and thus shouldn't be changed. 
public partial class [DatabaseContextName] : DbContext { ... }
Run Code Online (Sandbox Code Playgroud)

因此,在另一个文件中,您可以创建相同的定义并覆盖您想要的部分.

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

有部分类整体思路--did你注意到的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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 有一些答案,我希望我能投两次:) (7认同)
  • 您还应该覆盖SaveChangesAsync和SaveChangesAsync(CancellationToken) - 至少首先是代码的情况,首先不确定model/db. (3认同)
  • 使用 CodeFirst 时,显然不会生成 DbContext。但是,当您使用设计器时,会生成 DbContext 和 Entity 类,并且必须使用分部类覆盖它们。 (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
        }
    }
Run Code Online (Sandbox Code Playgroud)

像这样打电话:

context.SaveChangesWithErrors();
Run Code Online (Sandbox Code Playgroud)