[entity-framework-5] 패키지 관리자 콘솔 업데이트-데이터베이스 시드 방법 디버깅

패키지 관리자 콘솔에서 Seed()실행할 때 Entity Framework 데이터베이스 구성 클래스 의 메서드 를 디버깅하고 싶었지만 Update-Database수행 방법을 몰랐습니다. 같은 문제가있을 경우 다른 사람들과 솔루션을 공유하고 싶었습니다.



답변

정말 잘 작동하는 솔루션에 대한 비슷한 질문 이 있습니다.
필요하지 않습니다 Thread.Sleep.
이 코드를 사용하여 디버거를 시작합니다.

답변에서 잘림

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


답변

이 문제를 해결 한 방법은 Visual Studio의 새 인스턴스를 연 다음이 새 Visual Studio 인스턴스에서 동일한 솔루션을 여는 것입니다. 그런 다음 update-database 명령을 실행하는 동안이 새 인스턴스의 디버거를 이전 인스턴스 (devenv.exe)에 연결했습니다. 이를 통해 Seed 메서드를 디버깅 할 수있었습니다.

시간에 연결하지 않음으로써 중단 점을 놓치지 않았는지 확인하기 위해 중단 점 앞에 Thread.Sleep을 추가했습니다.

누군가에게 도움이되기를 바랍니다.


답변

특정 변수의 값을 가져와야하는 경우 빠른 해킹은 예외를 던지는 것입니다.

throw new Exception(variable);


답변

더 깨끗한 솔루션 (EF 6이 필요하다고 생각합니다)은 IMHO가 코드에서 update-database를 호출하는 것입니다.

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

이렇게하면 Seed 메서드를 디버깅 할 수 있습니다.

한 단계 더 나아가 빈 테스트 데이터베이스를 만들고, 모든 EF 마이그레이션을 적용하고, Seed 메서드를 실행하고, 테스트 데이터베이스를 다시 삭제하는 단위 테스트 (또는 더 정확하게는 통합 테스트)를 구성 할 수 있습니다.

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

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

Database.Delete("TestDatabaseNameOrConnectionString");

그러나 개발 데이터베이스에 대해 실행하지 않도록주의하십시오!


답변

이것이 오래된 질문이라는 것을 알고 있지만 원하는 것이 메시지 뿐이고 프로젝트에 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!")
      // ...
    }
  }
}


답변

Uh 디버깅은 한 가지이지만 context.Update () 호출하는 것을 잊지 마십시오.

또한 내부 예외가 콘솔에 쏟아지지 않고 try catch로 래핑하지 마십시오.
https://coderwall.com/p/fbcyaw/debug-into-entity-framework-code-first
with catch (DbEntityValidationException ex)


답변

두 가지 해결 방법이 있습니다 ( Debugger.Launch()나에게 적합하지 않기 때문에).

  1. 패키지 관리자 콘솔에서 메시지를 인쇄하려면 예외를 사용하십시오.
    throw new Exception("Your message");

  2. 또 다른 방법은 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);
    }