visual studio framework first datos crear con code entity-framework-5

entity-framework-5 - studio - framework base de datos



Depuración, gestor de paquetes, consola, actualización, base de datos, método de semilla (7)

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. A continuación, adjunté el depurador en esta nueva instancia a la instancia anterior (devenv.exe) mientras ejecutaba 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 colocarlo a tiempo, agregué un hilo. Duerma antes del punto de ruptura.

Espero que esto ayude a alguien.

Quería depurar el método Seed () en mi clase de configuración de base de datos de Entity Framework cuando ejecuto la base de datos de actualización desde la consola de Package Manager pero no sabía cómo hacerlo. Quería compartir la solución con otros en caso de que tengan el mismo problema.


Sé que esta es una vieja pregunta, pero si lo único que quieres son mensajes, y no te importa incluir referencias a WinForms en tu 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 Configuration.cs estándar

// ... 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!") // ... } } }


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

throw new Exception(variable);


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

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

  2. Otra forma es imprimir un mensaje en un 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); }



Una solución más limpia (supongo que esto requiere EF 6) sería en mi humilde opinión llamar a la base de datos de actualización 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 dar un paso más y construir una prueba unitaria (o, más precisamente, una prueba de integración) que crea una base de datos de prueba vacía, aplica todas las migraciones EF, ejecuta el método Seed y descarta la base de datos de prueba nuevamente:

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 en su base de datos de desarrollo!


Aquí hay una question similar con una solución que funciona realmente bien.
NO requiere Thread.Sleep .
Solo inicia el depurador utilizando este código.

Recortado de la respuesta

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