Depuración de Actualización de la Consola del Administrador de Paquetes-Método Semilla de la Base de Datos


Quería depurar el método Seed() en mi clase de configuración de la base de datos de Entity Framework cuando ejecutaba update-database desde la consola del Administrador de paquetes, pero no sabía cómo hacerlo. Quería compartir la solución con otros en caso de que tengan el mismo problema.

Author: Sachin Kainth, 2013-05-23

7 answers

Aquí es similar pregunta con una solución que funciona muy bien.
NO requiere Thread.Sleep.
Simplemente inicia el depurador usando este código.

Recortado de la respuesta

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-25 07:35:47

La forma en que resolví esto fue abrir una nueva instancia de Visual Studio y luego abrir la misma solución en esta nueva instancia de Visual Studio. Luego adjunté el depurador en esta nueva instancia a la instancia anterior (devenv.exe) mientras se ejecuta el comando update-database. Esto me permitió depurar el método Seed.

Solo para asegurarme de que no me perdí el punto de interrupción al no adjuntar a tiempo, agregué un hilo.Duerme antes del punto de interrupción.

Espero que esto ayude a alguien.
 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-23 15:52:44

Si necesita obtener el valor de una variable específica, un truco rápido es lanzar una excepción:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-18 11:42:17

Una solución más limpia (supongo que esto requiere EF 6) en mi humilde opinión sería llamar a update-database desde el código:

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

Esto le permite depurar el método Seed.

Puede ir un paso más allá y construir una prueba unitaria (o, más precisamente, una prueba de integración) que cree una base de datos de prueba vacía, aplique todas las migraciones EF, ejecute el método Seed y elimine la base de datos de prueba de nuevo:

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

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

Database.Delete("TestDatabaseNameOrConnectionString");

Pero tenga cuidado de no ejecutar esto contra su base de datos de desarrollo!

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-19 10:02:20

Sé que esta es una pregunta antigua, pero si todo lo que desea son mensajes, y no le importa incluir referencias a WinForms en su proyecto, hice una ventana de depuración simple donde puedo enviar eventos de seguimiento.

Para una depuración más seria y paso a paso, abriré otra instancia de Visual Studio, pero no es necesario para cosas simples.

Este es el código completo:

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);
    }
  }
}

Y en su estándar Configuración.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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-03 06:45:29

Uh Depuración es una cosa, pero no se olvide de llamar: contexto.Update ()

Tampoco envuelva en try catch sin un buen derrame de excepciones internas a la consola.
https://coderwall.com/p/fbcyaw/debug-into-entity-framework-code-first con 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-10 00:52:08

Tengo 2 soluciones (sin Debugger.Launch() ya que no funciona para mí):

  1. Para imprimir el mensaje en la consola del Administrador de paquetes, utilice la excepción:
    throw new Exception("Your message");

  2. Otra forma es imprimir el mensaje en el archivo creando un proceso cmd :


    // 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-19 13:28:50