EF Core: Add custom LINQ in Up method of Migration class

entity-framework entity-framework-core

Question

I would like to execute some LINQ in Up method of migrations. Problem is I don't know how can I get DbContext instance?

This is code generated by migrations add:

public partial class MyTableAddFieldTitle : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AddColumn<string>(
            name: "Title",
            table: "MyTable",
            nullable: true);
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropColumn(
            name: "Title",
            table: "MyTable");
    }
}

I would like to add something like that in Up method:

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.AddColumn<string>(
        name: "Title",
        table: "MyTable",
        nullable: true);

    var context = ?????;

    //Actual code is much more complicated, but the principle is the same.
    foreach (var item in context.Set<DbMyTable>())
      item.Title = item.SomeStringColumn;
    context.SaveChanges();
}

Problem is how to get context instance? I tried with DI in constructor:

protected MyTableAddFieldTitle(MyContext context)
{
}

but I get error:

MissingMethodException: No parameterless constructor defined for this object. System.RuntimeTypeHandle.CreateInstance(RuntimeType type, bool publicOnly, ref bool canBeCached, ref RuntimeMethodHandleInternal ctor)

1
2
3/21/2018 7:46:04 AM

Accepted Answer

I found solution.

In Startup class I defined static variable:

public static Func<MyContext> ContextFactory;

In constructor of Startup class I assigned variable:

public Startup(IHostingEnvironment env, IConfiguration config)
{
    MyContext GetContext(IConfiguration configuration, IHostingEnvironment environment)
    {
        var builder = new DbContextOptionsBuilder<MyContext>();
        builder.UseSqlServer(configuration["ConnectionStrings:Web"], b => b.MigrationsAssembly("Web.Hosting"));
        if (environment.IsDevelopment())
            builder.EnableSensitiveDataLogging();
        return new MyContext(builder.Options);
    }

    ContextFactory = () => GetContext(config, env);
}

Then in Migrations I simply call ContextFactory:

var context = Startup.ContextFactory();
context.Set<DbMyTable>().Where(....

To avoid error field does not exists I create 2 migration files (dotnet ef migrations add).
First adds field:

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.AddColumn<string>(
        name: "Title",
        table: "MyTable",
        nullable: true);
}

And second (empty) executes query:

protected override void Up(MigrationBuilder migrationBuilder)
{
    var context = Startup.ContextFactory();
    context.Set<DbMyTable>().Where(....
}
1
3/22/2018 9:16:17 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow