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)
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(....
}