调试程序包管理器控制台更新 - 数据库种子方法

时间:2013-05-23 15:52:44

标签: entity-framework-5

当我从Package Manager控制台运行Seed()但不知道如何操作时,我想在我的Entity Framework数据库配置类中调试Update-Database方法。我希望与其他人分享解决方案,以防他们遇到同样的问题。

7 个答案:

答案 0 :(得分:149)

以下是类似question的解决方案,效果非常好 它不需要Thread.Sleep
只需使用此代码启动调试器。

从答案中删除

if (!System.Diagnostics.Debugger.IsAttached) 
    System.Diagnostics.Debugger.Launch();

答案 1 :(得分:19)

我解决这个问题的方法是打开一个新的Visual Studio实例,然后在这个新的Visual Studio实例中打开相同的解决方案。然后,我在运行update-database命令时将此新实例中的调试器附加到旧实例(devenv.exe)。这允许我调试Seed方法。

为了确保我没有错过断点而没有及时附加断点,我在断点之前添加了一个Thread.Sleep。

我希望这有助于某人。

答案 2 :(得分:10)

如果你需要得到一个特定变量的值,快速的黑客就是抛出异常:

throw new Exception(variable);

答案 3 :(得分:5)

更清洁的解决方案(我想这需要EF 6)恕我直言可以从代码中调用update-database:

var configuration = new DbMigrationsConfiguration<TContext>();
var databaseMigrator = new DbMigrator(configuration);
databaseMigrator.Update();

这允许您调试Seed方法。

您可以更进一步,构建一个单元测试(或更确切地说,一个集成测试),创建一个空的测试数据库,应用所有EF迁移,运行Seed方法,然后再次删除测试数据库: / p>

var configuration = new DbMigrationsConfiguration<TContext>();
Database.Delete("TestDatabaseNameOrConnectionString");

var databaseMigrator = new DbMigrator(configuration);
databaseMigrator.Update();

Database.Delete("TestDatabaseNameOrConnectionString");

但是请注意不要在开发数据库中运行它!

答案 4 :(得分:3)

我知道这是一个老问题,但如果你想要的只是消息,并且你不想在你的项目中包含对WinForms的引用,我做了一些简单的调试窗口,我可以发送Trace事件。

对于更严肃和逐步调试,我将打开另一个Visual Studio实例,但它不是简单的东西。

这是整个代码:

<强> SeedApplicationContext.cs

using System;
using System.Data.Entity;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;

namespace Data.Persistence.Migrations.SeedDebug
{
  public class SeedApplicationContext<T> : ApplicationContext
    where T : DbContext
  {
    private class SeedTraceListener : TraceListener
    {
      private readonly SeedApplicationContext<T> _appContext;

      public SeedTraceListener(SeedApplicationContext<T> appContext)
      {
        _appContext = appContext;
      }

      public override void Write(string message)
      {
        _appContext.WriteDebugText(message);
      }

      public override void WriteLine(string message)
      {
        _appContext.WriteDebugLine(message);
      }
    }

    private Form _debugForm;
    private TextBox _debugTextBox;
    private TraceListener _traceListener;

    private readonly Action<T> _seedAction;
    private readonly T _dbcontext;

    public Exception Exception { get; private set; }
    public bool WaitBeforeExit { get; private set; }

    public SeedApplicationContext(Action<T> seedAction, T dbcontext, bool waitBeforeExit = false)
    {
      _dbcontext = dbcontext;
      _seedAction = seedAction;
      WaitBeforeExit = waitBeforeExit;
      _traceListener = new SeedTraceListener(this);
      CreateDebugForm();
      MainForm = _debugForm;
      Trace.Listeners.Add(_traceListener);
    }

    private void CreateDebugForm()
    {
      var textbox = new TextBox {Multiline = true, Dock = DockStyle.Fill, ScrollBars = ScrollBars.Both, WordWrap = false};
      var form = new Form {Font = new Font(@"Lucida Console", 8), Text = "Seed Trace"};
      form.Controls.Add(tb);
      form.Shown += OnFormShown;
      _debugForm = form;
      _debugTextBox = textbox;
    }

    private void OnFormShown(object sender, EventArgs eventArgs)
    {
      WriteDebugLine("Initializing seed...");
      try
      {
        _seedAction(_dbcontext);
        if(!WaitBeforeExit)
          _debugForm.Close();
        else
          WriteDebugLine("Finished seed. Close this window to continue");
      }
      catch (Exception e)
      {
        Exception = e;
        var einner = e;
        while (einner != null)
        {
          WriteDebugLine(string.Format("[Exception {0}] {1}", einner.GetType(), einner.Message));
          WriteDebugLine(einner.StackTrace);
          einner = einner.InnerException;
          if (einner != null)
            WriteDebugLine("------- Inner Exception -------");
        }
      }
    }

    protected override void Dispose(bool disposing)
    {
      if (disposing && _traceListener != null)
      {
        Trace.Listeners.Remove(_traceListener);
        _traceListener.Dispose();
        _traceListener = null;
      }
      base.Dispose(disposing);
    }

    private void WriteDebugText(string message)
    {
      _debugTextBox.Text += message;
      Application.DoEvents();
    }

    private void WriteDebugLine(string message)
    {
      WriteDebugText(message + Environment.NewLine);
    }
  }
}

在您的标准 Configuration.cs

// ...
using System.Windows.Forms;
using Data.Persistence.Migrations.SeedDebug;
// ...

namespace Data.Persistence.Migrations
{
  internal sealed class Configuration : DbMigrationsConfiguration<MyContext>
  {
    public Configuration()
    {
      // Migrations configuration here
    }

    protected override void Seed(MyContext context)
    {
      // Create our application context which will host our debug window and message loop
      var appContext = new SeedApplicationContext<MyContext>(SeedInternal, context, false);
      Application.Run(appContext);
      var e = appContext.Exception;
      Application.Exit();
      // Rethrow the exception to the package manager console
      if (e != null)
        throw e;
    }

    // Our original Seed method, now with Trace support!
    private void SeedInternal(MyContext context)
    {
      // ...
      Trace.WriteLine("I'm seeding!")
      // ...
    }
  }
}

答案 5 :(得分:1)

呃调试是一回事,但不要忘记打电话: context.Update()

在没有良好的内部异常泄漏的情况下,也不要将try catch包裹在控制台中 https://coderwall.com/p/fbcyaw/debug-into-entity-framework-code-first with catch(DbEntityValidationException ex)

答案 6 :(得分:0)

我有2个解决方法(没有Debugger.Launch(),因为它对我不起作用):

  1. 要在Package Manager Console中打印消息,请使用例外:
    throw new Exception("Your message");

  2. 另一种方法是通过创建cmd进程在文件中打印消息:

  3. 
        // Logs to file {solution folder}\seed.log data from Seed method (for DEBUG only)
        private void Log(string msg)
        {
            string echoCmd = $"/C echo {DateTime.Now} - {msg} >> seed.log";
            System.Diagnostics.Process.Start("cmd.exe", echoCmd);
        }