Ich habe eine ASP.NET MVC 6-Anwendung und muss die Methoden Database.EnsureCreated
und aufrufen Database.Migrate
.
Aber wo soll ich sie anrufen?
asp.net
asp.net-mvc
entity-framework
entity-framework-core
Bailando Bailando
quelle
quelle
Antworten:
Ich denke, das ist eine wichtige Frage und sollte gut beantwortet werden!
Was ist Database.EnsureCreated?
context.Database.EnsureCreated()
ist eine neue EF-Kernmethode, die sicherstellt, dass die Datenbank für den Kontext vorhanden ist. Wenn es existiert, wird keine Aktion ausgeführt. Wenn es nicht vorhanden ist, werden die Datenbank und ihr gesamtes Schema erstellt und es wird sichergestellt, dass es mit dem Modell für diesen Kontext kompatibel ist.Hinweis: Diese Methode verwendet keine Migrationen zum Erstellen der Datenbank. Darüber hinaus kann die erstellte Datenbank später nicht mithilfe von Migrationen aktualisiert werden. Wenn Sie auf eine relationale Datenbank abzielen und Migrationen verwenden, können Sie mithilfe der
DbContext.Database.Migrate()
Methode sicherstellen, dass die Datenbank erstellt und alle Migrationen angewendet werden.Wie haben wir das mit EF 6 gemacht?
context.Database.EnsureCreated()
entspricht den unten aufgeführten Ansätzen von EF 6:Paketmanager-Konsole:
Enable-Migrations -EnableAutomaticMigrations. Add-Migration / Update-Datenbank.
Aus dem Code:
Database.SetInitializer CreateDatabaseIfNotExists
oder
Mit DbMigrationsConfiguration und setzen Sie AutomaticMigrationsEnabled = true;
Was ist Database.Migrate?
Wendet alle ausstehenden Migrationen für den Kontext auf die Datenbank an. Erstellt die Datenbank, falls sie noch nicht vorhanden ist.
Wie haben wir das mit EF 6 gemacht?
context.Database.Migrate()
entspricht den unten aufgeführten Ansätzen von EF 6:Paketmanager-Konsole:
Update-Database -TargetMigration
Mit einer benutzerdefinierten DbMigrationsConfiguration:
AutomaticMigrationsEnabled = false; oder mit DbMigrator.
Fazit :
Wenn Sie Migrationen verwenden, gibt es
context.Database.Migrate()
. Wenn Sie keine Migrationen und nur eine schnelle Datenbank (normalerweise zum Testen) möchten, verwenden Sie context.Database.EnsureCreated () / EnsureDeleted ().quelle
Database.Migrate()
Migrationen (falls erforderlich) erstellt werden und dann die darauf basierende Basis aktualisiert wird. Ähnlich wie bei der automatischen Migration in EF 6. Aber ich habe mich geirrt. Es werden nur vorhandene Migrationen (falls vorhanden) in der Datenbank angewendet.Mit den Informationen, die James P und Bassam Alugili zur Verfügung stellten, fügte ich der
Configure
Methode in derStartup
Klasse ( Startup.cs ) diese Codezeilen hinzu :using (var scope = app.ApplicationServices.CreateScope()) using (var context = scope.ServiceProvider.GetService<MyDbContext>()) context.Database.Migrate();
quelle
Nur als Vorwort sollten Sie dies von Rowan Miller lesen :
Nach beantworten hier müssen Sie fügen
Globals.EnsureDatabaseCreated();
es zuStartup.cs
:Startfunktion in Startup.cs :
public Startup(IHostingEnvironment env) { // Set up configuration sources. var builder = new ConfigurationBuilder() .AddJsonFile("appsettings.json") .AddEnvironmentVariables(); if (env.IsDevelopment()) { // This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately. builder.AddApplicationInsightsSettings(developerMode: true); } Configuration = builder.Build(); Globals.Configuration = Configuration; Globals.HostingEnvironment = env; Globals.EnsureDatabaseCreated(); }
Und definieren Sie
Globals.EnsureDatabaseCreated()
wie folgt:public static void EnsureDatabaseCreated() { var optionsBuilder = new DbContextOptionsBuilder(); if (HostingEnvironment.IsDevelopment()) optionsBuilder.UseSqlServer(Configuration["Data:dev:DataContext"]); else if (HostingEnvironment.IsStaging()) optionsBuilder.UseSqlServer(Configuration["Data:staging:DataContext"]); else if (HostingEnvironment.IsProduction()) optionsBuilder.UseSqlServer(Configuration["Data:live:DataContext"]); var context = new ApplicationContext(optionsBuilder.Options); context.Database.EnsureCreated(); optionsBuilder = new DbContextOptionsBuilder(); if (HostingEnvironment.IsDevelopment()) optionsBuilder.UseSqlServer(Configuration["Data:dev:TransientContext"]); else if (HostingEnvironment.IsStaging()) optionsBuilder.UseSqlServer(Configuration["Data:staging:TransientContext"]); else if (HostingEnvironment.IsProduction()) optionsBuilder.UseSqlServer(Configuration["Data:live:TransientContext"]); new TransientContext(optionsBuilder.Options).Database.EnsureCreated(); }
Zur Verwendung
context.Database.Migrate()
siehe hier oder hier .quelle
Globals
. Dies scheint eine nicht standardmäßige Methode zu sein, um dies zu verhindernNormalerweise
DbContext
wird das dem Abhängigkeitsinjektionsbehälter folgendermaßen hinzugefügtStartup.ConfigureServices()
:public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { // Add DbContext to the injection container services.AddDbContext<MyDbContext>(options => options.UseSqlServer( this.Configuration.GetConnectionString("DefaultConnection"))); } }
Der fungiert
IServiceCollection
jedoch nicht als Dienstanbieter, und da der vor dem aktuellen Bereich ( )DbContext
nicht beim Injektionscontainer registriert wurde , können wir hier nicht über die Abhängigkeitsinjektion auf den Kontext zugreifen.Startup.ConfigureServices
Henk Mollema bespricht manuell lösen Dienste während des Starts hier , aber erwähnt , dass ...
Henk erwähnt auch, dass die
Startup
Abhängigkeitsinjektion des Konstruktors sehr begrenzt ist und keine in konfigurierten Dienste enthältStartup.ConfigureServices()
, sodass die Verwendung von DbContext über den im Rest der App verwendeten Injektionscontainer am einfachsten und am besten geeignet ist.Um anzurufen
Database.EnsureCreated()
oderDatabase.Migrate()
, können und möchten wir den DbContext automatisch auflösen lassenStartup.Configure()
, wo unsere konfigurierten Dienste jetzt über DI verfügbar sind:public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { // Add DbContext to the injection container services.AddDbContext<MyDbContext>(options => options.UseSqlServer( this.Configuration.GetConnectionString("DefaultConnection"))); } public static void Configure(IApplicationBuilder app, IWebHostEnvironment env, MyDbContext context) { if (env.IsDevelopment()) { context.Database.EnsureCreated(); //context.Database.Migrate(); } } }
Bitte denken Sie daran , wie Bassam Alugili Antwort von EF Core - Dokumentation verwiesen , dass
Database.EnsureCreated()
undDatabase.Migrate()
nicht zusammen sein sollen verwendet , da stellt man sicher , Ihre bestehende Migrationen auf die Datenbank angewendet werden, die bei Bedarf erstellt wird. Die andere Methode stellt lediglich sicher, dass eine Datenbank vorhanden ist, und erstellt, falls nicht, eine Datenbank, die Ihre Datenbank widerspiegeltDbContext
, einschließlich aller über die Fluent-API im Kontext vorgenommenen Seeding-Vorgänge.quelle
Außerdem kann es zu Leistungseinbußen kommen, wenn Sie dies im Konstruktor Ihres Kontexts aufrufen ... Nachdem
EnsureCreated
ich zum Dienstprogramm setup.cs gewechselt bin, habe ich erhebliche Verbesserungen meiner Antwortzeiten festgestellt.Hinweis: Ich verwende EFC und UWP.
quelle