Where can I find the console or debug output from

2019-04-17 18:46发布

问题:

I'm using EntityFramework code first with migrations. From the package manager console, I'm running "update-database". This executes Configuration.Seed(context) which I have overridden.

    protected override void Seed(WebContext context)
    {

        Console.WriteLine("Console Test");
        Debug.WriteLine("Debug Test");
        Trace.WriteLine("Trace Test");
    }

Where can I find that output?

Better yet, How do I output back to the package manager window?

Thx, Dan

回答1:

Where can I find that output?

Sorry, but the quick answer is basically nowhere.

To be precise at least not in the package manager console.

Debug.WriteLine("Debug Test");
Trace.WriteLine("Trace Test");

You can see the output of the Debug... and Trace... methods if you attach another Visual Studio to debug the Visual Studio instance which is running the update-database command. Then in the debuggin VS you can see the output in the Output Window.

Console.WriteLine("Console Test");

You can see the output of the Console... methods if you run the migrations with the migrate.exe command line tool which comes with EF:

How do I output back to the package manager window?

I have here also bad news, after a quick "reflectoring": with the current implementation of the EF migrations it's not supported to display custom information during execution of the update-database (or any other command).



回答2:

A quick hack I use to be able to quickly find a value in my Seed method is simply to throw an exception with a value I care about, e.g.

throw new Exception(yourValue);

This errors out the Seed, but my exception/value appears in my package manager console.



回答3:

Running a SQL print command will write to the Package Manager Console. Here is a helper method that I use:

    /// <summary>
    /// write a message to the Package Manager Console
    /// </summary>
    public void Debug(string s, params object[] args)
    {
        var fullString = string.Format(s, args).Replace("'", "''");
        Sql(string.Format("print '{0}'", fullString));
    }


回答4:

My needs were similar to yours so I figured I'd document them here in case they could help someone else out. My goal was to display all of the output from the migrations including all of the sql run as part of the Seed method. As a side effect of this solution, you will also be able to see any Debug.Write message in your code.

First create a DebugMigrationsLogger that will write all migration output to Debug.WriteLine (thanks to http://whiteknight.github.io/2013/01/26/efcodeonlymigrations.html):

public class DebugMigrationsLogger : System.Data.Entity.Migrations.Infrastructure.MigrationsLogger
{
    public override void Info(string message)
    {
        Debug.WriteLine(message);
    }
    public override void Verbose(string message)
    {
        Debug.WriteLine(message);
    }
    public override void Warning(string message)
    {
        Debug.WriteLine("WARNING: " + message);
    }
}

Next make sure you have a subclass of DbMigrationsConfiguration for your DbContext:

public class MyDbMigrationsConfiguration : DbMigrationsConfiguration<MyDbContext>
{
    public MyDbMigrationsConfiguration()
    {
    }
    protected override void Seed(MartusDb db)
    {
        //...
    }
}

Next you run your migrations as an on-demand unit test so your test runner can capture the output. My unit test looks something like this:

public void MigrateDb_Test() 
{
    var config = new MyDbMigrationsConfiguration { AutomaticMigrationDataLossAllowed = true };
    var migrator = new DbMigrator(config);
    var loggingDecorator = new MigratorLoggingDecorator(migrator, new DebugMigrationsLogger());
    loggingDecorator.Update();
}

Lastly, set the Database.Log in your DbContext constructor:

public class MyDbContext : DbContext
{
    public MyDbContext()
    {
        Database.Log = message => Debug.WriteLine(message);
    }
}

Now whenever you run the MigrateDb_Test() you will see all the output, it has made debugging migrations so much easier for me!



回答5:

Dirty workaround extending George's answer.

protected override void Seed(YourContext context)
{
    using (var seedout = new StringWriter())
    {
        // do your work
        context.Authors.AddOrUpdate(x => x.Id,
            new Author() { Id = 1, Name = "Jane Austen" }
            );

        // some message
        seedout.WriteLine("some message");

        // commit your work
        context.SaveChanges();

        seedout.WriteLine("Seed successfully completed.");

        // dummy exception to show message on package manager console
        throw new Exception(seedout.ToString());
    }
}