debugging程序包pipe理器控制台更新数据库种子方法
我想在我的entity framework数据库configuration类中debuggingSeed()方法时,我从包pipe理器控制台运行update-database,但不知道如何去做。 我想与其他人分享解决scheme,以防他们遇到同样的问题。
这是一个类似的问题 ,一个很好的解决scheme。 不需要thread.sleep。 使用代码启动debugging器。
从答案削减
if (!System.Diagnostics.Debugger.IsAttached) System.Diagnostics.Debugger.Launch();
我解决这个问题的方法是打开Visual Studio的一个新实例,然后在这个新的Visual Studio实例中打开相同的解决scheme。 然后,在运行update-database命令时,将此新实例中的debugging器附加到旧实例(devenv.exe)中。 这使我能够debuggingSeed方法。
只是为了确保我没有错过断点,因为没有附上时间,我在断点之前添加了一个Thread.Sleep。
我希望这可以帮助别人。
如果你需要得到一个特定的variables的值,一个简单的黑客就是抛出一个exception:
throw new Exception(variable);
我知道这是一个古老的问题,但如果你想要的只是消息,而且你不关心在项目中包含对WinForms的引用,那么我可以发送一些简单的debugging窗口来发送Trace事件。
为了更加严肃和循序渐进的debugging,我将打开另一个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!") // ... } } }
一个更清洁的解决scheme(我想这需要EF 6)恕我直言,是从代码调用更新数据库:
var configuration = new DbMigrationsConfiguration<TContext>(); var databaseMigrator = new DbMigrator(configuration); databaseMigrator.Update();
这使您可以debuggingSeed方法。
您可以采取这一步,并构build一个unit testing(或更准确地说,一个集成testing),创build一个空的testing数据库,应用所有EF迁移,运行Seed方法,并再次丢弃testing数据库:
var configuration = new DbMigrationsConfiguration<TContext>(); Database.Delete("TestDatabaseNameOrConnectionString"); var databaseMigrator = new DbMigrator(configuration); databaseMigrator.Update(); Database.Delete("TestDatabaseNameOrConnectionString");
但要小心,不要在您的开发数据库中运行此操作!
debugging是一回事,但不要忘记调用:context.Update()
也不要在没有好的内部exception的情况下尝试捕获包装溢出到控制台。
https://coderwall.com/p/fbcyaw/debug-into-entity-framework-code-first with catch(DbEntityValidationException ex)
我有2个解决方法(没有Debugger.Launch()
因为它不适合我):
-
要在Package Manager Console中打印消息,请使用exception:
throw new Exception("Your message");
-
另一种方法是通过创build
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); }