डिबगिंग पैकेज मैनेजर कंसोल अपडेट-डेटाबेस सीड मेथड


106

Seed()जब मैं Update-Databaseपैकेज मैनेजर कंसोल से चलाता हूं, तो मैं अपने एंटिटी फ्रेमवर्क डेटाबेस कॉन्फ़िगरेशन क्लास में विधि को डीबग करना चाहता था, लेकिन यह नहीं पता था कि यह कैसे करना है। मैं दूसरों के साथ समाधान साझा करना चाहता था यदि उनके पास एक ही मुद्दा हो।

जवाबों:


158

यहां एक समाधान के साथ इसी तरह का सवाल है जो वास्तव में अच्छी तरह से काम करता है।
इसकी आवश्यकता नहीं है Thread.Sleep
बस इस कोड का उपयोग करके डीबगर लॉन्च करता है।

जवाब से फँस गया

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

@tchelidze migrate.exeवर्तमान में चल रहे दृश्य स्टूडियो को संलग्न करने के लिए आप कंसोल से कॉल कर सकते हैं। इस उत्तर में एमओआरई जानकारी: stackoverflow.com/a/52700520/350384
Mariusz Pawelski

20

जिस तरह से मैंने इसे हल किया वह विज़ुअल स्टूडियो का एक नया उदाहरण खोलने के लिए था और फिर विज़ुअल स्टूडियो के इस नए उदाहरण में एक ही समाधान खोलें। फिर मैंने इस नए उदाहरण में डिबगर को पुराने डेटाबेस (devenv.exe) से अपडेट-डेटाबेस कमांड चलाते हुए संलग्न किया। इसने मुझे बीज विधि को डीबग करने की अनुमति दी।

बस यह सुनिश्चित करने के लिए कि मैंने ब्रेकपॉइंट को समय से न जोड़कर याद किया, मैंने ब्रेकप्वाइंट से पहले एक थ्रेड मिला दिया।

मुझे उम्मीद है इससे किसी को सहायता मिलेगी।


12

यदि आपको एक विशिष्ट चर मान प्राप्त करने की आवश्यकता है, तो एक त्वरित हैक एक अपवाद फेंकने के लिए है:

throw new Exception(variable);

3
त्वरित और गंदा :)
DanKodi

5

एक क्लीनर समाधान (मुझे लगता है कि इसके लिए EF 6 की आवश्यकता है) IMHO कोड से अपडेट-डेटाबेस को कॉल करने के लिए होगा:

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

यह आपको बीज विधि को डीबग करने की अनुमति देता है।

आप इसे एक कदम आगे ले जा सकते हैं और एक इकाई परीक्षण का निर्माण कर सकते हैं (या, अधिक सटीक रूप से, एक एकीकरण परीक्षण) जो एक खाली परीक्षण डेटाबेस बनाता है, सभी EF माइग्रेशन लागू करता है, बीज विधि चलाता है, और फिर से परीक्षण डेटाबेस को गिराता है:

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

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

Database.Delete("TestDatabaseNameOrConnectionString");

लेकिन अपने विकास डेटाबेस के खिलाफ इसे चलाने के लिए सावधान रहें!


1
EF Core में चूंकि DbMigrationsConfiguration क्लास नहीं है, इसके बजाय myDbContext.Database.GetPendingMigrations () का उपयोग करें।
stevie_c

3

मुझे पता है कि यह एक पुराना सवाल है, लेकिन अगर आप चाहते हैं कि सभी संदेश हैं, और आप अपने प्रोजेक्ट में WinForms के संदर्भों को शामिल करने की परवाह नहीं करते हैं, तो मैंने कुछ सरल डिबग विंडो बनाई जहां मैं ट्रेस इवेंट भेज सकता हूं।

अधिक गंभीर और चरण-दर-चरण डिबगिंग के लिए, मैं एक और विज़ुअल स्टूडियो इंस्टेंस खोलूंगा, लेकिन यह साधारण सामान के लिए आवश्यक नहीं है।

यह पूरा कोड है:

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

1
बेशक, डिबग विंडो जितनी चाहें उतनी जटिल हो सकती है (आप एक पूर्ण रूप बनाने के लिए डिजाइनर का उपयोग भी कर सकते हैं और इसे पास SeedInternalकर सकते हैं ताकि विधि इसका उपयोग कर सके)
Jcl

1

उह डिबगिंग एक बात है, लेकिन कॉल करना न भूलें: संदर्भ।

कंसोल के लिए एक अच्छा आंतरिक अपवाद स्पिल के बिना ट्रैप कैच में न लपेटें।
https://coderwall.com/p/fbcyaw/debug-into-entity-framework-code-first with catch (DbEntityValidationException ex)


कृपया इस URL की जाँच करें यह आपकी सामग्री की गुणवत्ता को ऊपर उठाने के लिए उपयोगी होगा
विली चेंग

0

मेरे पास 2 वर्कअराउंड हैं ( 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);
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.