调试代码优先的实体框架迁移代码

Posted

技术标签:

【中文标题】调试代码优先的实体框架迁移代码【英文标题】:Debug code-first Entity Framework migration codes 【发布时间】:2013-06-14 16:13:30 【问题描述】:

我首先在我的网站中使用实体框架代码,我只是想知道是否有任何方法可以调试迁移代码。你知道,比如设置断点之类的东西。

我正在使用包管理器控制台使用 Update-Database 更新数据库。

谢谢

【问题讨论】:

这只是标准的 C# 代码 - 所以是的,当然,您可以在其中设置断点..... 但应用程序实际上并没有运行,因为我正在使用包管理器控制台。 然后不要从包管理控制台升级,而是将迁移初始化程序设置为默认初始化程序,以便在您的应用程序第一次连接到它时迁移数据库。 我正在使用迁移代码更新我的数据库,但我无法停止应用并再次运行它以运行初始化程序。 我不使用SQL的原因是更新的代码比较复杂,几乎不可能用SQL来实现。 【参考方案1】:

我知道 EF Code First Migrations 是一个相对较新的工具,但别忘了你还在 .NET 中。

所以你可以使用:

if (System.Diagnostics.Debugger.IsAttached == false)

    System.Diagnostics.Debugger.Launch();

之后你可以看到你的 InnerException。

或者你可以像这样使用 try...catch 语句: Exception handling Entity Framework

【讨论】:

是的,这在通过包管理器控制台运行更新数据库时有效。非常方便! 我将此添加到我的 Configuration.Seed 方法的顶部。它会导致一个弹出窗口,让您选择您的 Visual Studio 来调试代码。但是,当我选择它时,我的系统会挂起(可能不相关)。 这段代码放在哪里?如果有人可以帮忙!谢谢。 在你的配置类的构造函数中。 @Talon 去喝杯咖啡,等你回来的时候,可能会弹出另一个 Visual Studio 实例。 :)【参考方案2】:

要在数据库迁移中遇到断点,请在初始化时将上下文设置为 MigrateDatabaseToLatestVersion。

Database.SetInitializer(new MigrateDatabaseToLatestVersion<EnterContextHere, Configuration>());

然后您只需正常调试(使用 f5 运行),断点将在您第一次运行项目时命中。

现在的问题是,如果您第二次调试,迁移将无法运行。这是因为 __MigrationHistory 表已更新,表明您已迁移到最新版本。要重新测试迁移,请打开包管理器控制台并降级到之前的迁移:

Update-Database –TargetMigration: ThePreviousMigrationName

【讨论】:

【参考方案3】:

我的回答可能有点傻,但无论如何都可以。 如果您像我一样,有时在 Seed() 方法中遇到问题,我通常会简单地创建一个调用 Protect Seed() 的公共方法。

public void SeedDebug(AppDbContext context)

    Seed(context);

然后在我的 HomeController 中,我在 Debug 模式下调用此方法。

public class HomeController : Controller

    var appDb = new AppDbContext();
    public ActionResult Index()
    
        var config = new Configuration();
        config.SeedDebug(appDb);
        return View();
    

我知道这是一个有点蹩脚的解决方案,但它简单快捷。 当然,这必须在模型创建后完成。 所以一步一步来:

    注释种子方法并执行更新数据库创建模型

    取消注释方法 Seed() 并插入我上面提到的“hack”。

    在配置中禁用自动迁移

    AutomaticMigrationsEnabled = false;//如果你禁用了这个已经跳过这一步

    调试您的应用程序,修复错误并移除“hack”

【讨论】:

【参考方案4】:

这里有一个更防失败的方法,它可以轻松解决问题:

第 1 步:将这段代码放在要调试的迁移的正上方:

public partial class ORACLE_Test : DbMigration

    public override void Up()
    
        if (!System.Diagnostics.Debugger.IsAttached)
            System.Diagnostics.Debugger.Launch();

        AddColumn("TEST", "UR_USER_ID", x => x.Decimal(nullable: false, precision: 11, scale: 0, storeType: "number"));
        AddColumn("TEST", "UR_CLIENT_ID", x => x.Decimal(nullable: false, precision: 11, scale: 0, storeType: "number"));
        [...]
    

    public override void Down()
    
    

步骤#2:编译包含您的迁移的项目

步骤#3:在包含迁移的 dll 的输出目录(/bin/Debug、/bin/Release 等)中打开一个控制台

步骤#4:使用 /scriptFile 参数调用 migrate.exe 以启动调试器并实际调试所需的 db-migration

migrate.exe "Your.Migrations.Assembly.dll" /scriptFile="foo.sql" /verbose /startupConfigurationFile="Your.Migrations.Assembly.config"

一旦弹出调试器选择器对话框,选择您已经打开的 Visual Studio 实例。

【讨论】:

【参考方案5】:

您可以在迁移代码中添加 Console.WriteLine 语句(不是一个很好的解决方案)

请注意,仅当您使用migrate.exe 实用程序(在pacakges\EntityFramework.x.y.z\tools 中)运行迁移代码时才会显示这些消息。如果您通过包管理器控制台运行迁移,它们将不会显示。

【讨论】:

谢谢汤姆...这是我能得到的最接近的答案。如果没有人用更好的解决方案回答这个问题,我会将其标记为答案。 :) 或者在你想要返回的消息中抛出一个异常。【参考方案6】:

我在其他地方使用“Debugger.Launch()”(如m_david's answer above)很幸运,但在 CreateDbContext 内部,它似乎以某种方式既附加又不附加。我的意思是,它附加并开始尝试进入 .asm 文件和 .cpp 文件(内部代码)。如果我尝试在 Console.Writeline 上设置断点,我知道之后会执行(我可以看到任何“dotnet ef migrations COMMAND”的输出)它都会执行它并且永远不会到达断点。

这对我有用:

while (!System.Diagnostics.Debugger.IsAttached)
    System.Threading.Thread.Sleep(10);

// Breakpoint after this...

您可以使用 Visual Studio 执行迁移并手动附加,它实际上让您可以像您期望的那样逐步执行代码,只是更痛苦。我真正应该尝试的是两种方法的结合......

【讨论】:

你附加到哪个进程?【参考方案7】:

我还发现了一个巧妙的技巧here 来获取错误详细信息...

基本上,诀窍是从异常中获取所有信息,将其放入字符串中,然后使用生成的字符串和原始异常抛出一个新的 DbEntityValidationException。

【讨论】:

以上是关于调试代码优先的实体框架迁移代码的主要内容,如果未能解决你的问题,请参考以下文章

独立于模式的实体框架代码优先迁移

实体框架代码优先:启用迁移错误

实体框架 - 迁移 - 代码优先 - 每次迁移播种

无法在 .NET 中的实体框架代码优先方法中迁移 AspNetUser 实体

如何为实体框架代码优先迁移设置隔离级别

实体框架代码优先迁移 - 我可以针对以前的迁移