Ich möchte einige LINQ in Up-Methode von Migrationen ausführen. Problem ist, ich weiß nicht, wie kann ich DbContext-Instanz bekommen?
Dies ist Code, der von migrations add
generiert wird:
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");
}
}
Ich möchte etwas in der Up
Methode hinzufügen:
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 ist, wie man Kontextinstanz erhält? Ich habe mit DI im Konstruktor versucht:
protected MyTableAddFieldTitle(MyContext context)
{
}
aber ich bekomme Fehler:
MissingMethodException: Für dieses Objekt ist kein parameterloser Konstruktor definiert. System.RuntimeTypeHandle.CreateInstance (RuntimeType-Typ, bool publicOnly, ref bool kannBeCached, ref RuntimeMethodHandleInternal ctor)
Ich habe eine Lösung gefunden.
In der Startup
Klasse habe ich eine statische Variable definiert:
public static Func<MyContext> ContextFactory;
Im Konstruktor der Startup
Klasse habe ich die Variable zugewiesen:
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);
}
In Migrationen rufe ich ContextFactory
einfach ContextFactory
:
var context = Startup.ContextFactory();
context.Set<DbMyTable>().Where(....
Um ein dotnet ef migrations add
zu vermeiden, existiere ich nicht. Ich erstelle 2 Migrationsdateien ( dotnet ef migrations add
).
Zuerst fügt Feld hinzu:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Title",
table: "MyTable",
nullable: true);
}
Und zweitens (leer) führt Abfrage aus:
protected override void Up(MigrationBuilder migrationBuilder)
{
var context = Startup.ContextFactory();
context.Set<DbMyTable>().Where(....
}