Debugging Package Manager Console Update-Database Seed Method

Chciałem debugować metodę Seed() w mojej klasie konfiguracji bazy danych Entity Framework podczas uruchamiania update-database z konsoli Menedżera pakietów, ale nie wiedziałem jak to zrobić. Chciałem podzielić się rozwiązaniem z innymi w przypadku, gdy mają ten sam problem.

Author: Sachin Kainth, 2013-05-23

7 answers

Oto podobne pytanie z rozwiązaniem, które działa naprawdę dobrze.
Nie wymaga Thread.Sleep.
Po prostu uruchamia debugger używając tego kodu.

Wycięte z odpowiedzi

if (!System.Diagnostics.Debugger.IsAttached) 
    System.Diagnostics.Debugger.Launch();
 138
Author: EthR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-25 07:35:47

Sposobem, w jaki to rozwiązałem, było otwarcie nowej instancji Visual Studio, a następnie otwarcie tego samego rozwiązania w nowej instancji Visual Studio. Następnie podłączyłem debugger w tej nowej instancji do starej instancji (devenv.exe) podczas uruchamiania polecenia update-database. To pozwoliło mi debugować metodę Seed.

Aby upewnić się, że nie przegapiłem punktu przerwania, nie dołączając się na czas, dodałem wątek.Spać przed punktem przerwania.

Mam nadzieję, że to komuś pomoże.

 17
Author: Sachin Kainth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-23 15:52:44

Jeśli chcesz uzyskać wartość określonej zmiennej, szybkim włamaniem jest rzucenie wyjątku:

throw new Exception(variable);
 9
Author: cederlof,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-18 11:42:17

Czystszym rozwiązaniem (chyba wymaga to EF 6) byłoby IMHO wywołanie update-database z kodu:

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

To pozwala debugować metodę Seed.

Możesz pójść o krok dalej i zbudować test jednostkowy (a dokładniej test integracyjny), który utworzy pustą bazę testową, zastosuje wszystkie migracje EF, uruchomi metodę Seed i ponownie upuści bazę testową:

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

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

Database.Delete("TestDatabaseNameOrConnectionString");

Ale uważaj, aby nie uruchomić tego z bazy danych rozwoju!

 3
Author: Jesper Mygind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-19 10:02:20

Wiem, że to stare pytanie, ale jeśli wszystko, co chcesz to wiadomości, i nie obchodzi cię, aby zawierać odniesienia do WinForms w swoim projekcie, zrobiłem proste Okno debugowania, gdzie mogę wysłać śledzenie zdarzeń.

Dla poważniejszego i krok po kroku debugowania, otworzę kolejną instancję Visual Studio, ale nie jest to konieczne dla prostych rzeczy.

To jest cały kod:

Seed Applicationkontekst.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);
    }
  }
}

I na swoim standardzie Konfiguracja.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!")
      // ...
    }
  }
}
 2
Author: Jcl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-03 06:45:29

Uh debugowanie to jedno, ale nie zapomnij zadzwonić: kontekst.Update ()

Również nie owijaj spróbuj złapać bez dobrych wewnętrznych WYJĄTKÓW rozlać do konsoli.
https://coderwall.com/p/fbcyaw/debug-into-entity-framework-code-first with catch (DbEntityValidationException ex)

 1
Author: Steven Packham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-10 00:52:08

Mam 2 obejścia (Bez Debugger.Launch() Ponieważ mi nie działa):

  1. Aby wydrukować wiadomość w konsoli Menedżera pakietów, użyj wyjątku:
    throw new Exception("Your message");

  2. Innym sposobem jest wypisanie wiadomości w pliku poprzez utworzenie cmd procesu:


    // 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);
    }
 0
Author: Gendolph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-19 13:28:50