DatenseedingData Seeding

Datenseeding ist der Vorgang, bei dem eine Datenbank mit einem anfänglichen Satz von Daten gefüllt wird.Data seeding is the process of populating a database with an initial set of data.

Es gibt mehrere Möglichkeiten, wie dies in EF Core erreicht werden kann:There are several ways this can be accomplished in EF Core:

  • Modellseed-DatenModel seed data
  • Anpassung der manuellen MigrationManual migration customization
  • Benutzerdefinierte Initialisierungs LogikCustom initialization logic

Modellseed-DatenModel seed data

Anders als in EF6 kann das Seeding von Daten in EF Core einem Entitätstyp als Teil der Modell Konfiguration zugeordnet werden.Unlike in EF6, in EF Core, seeding data can be associated with an entity type as part of the model configuration. Anschließend können EF Core Migrationen automatisch berechnen, welche INSERT-, Update-oder DELETE-Vorgänge angewendet werden müssen, wenn die Datenbank auf eine neue Version des Modells aktualisiert wird.Then EF Core migrations can automatically compute what insert, update or delete operations need to be applied when upgrading the database to a new version of the model.

Hinweis

Bei Migrationen werden Modelländerungen nur berücksichtigt, wenn bestimmt wird, welcher Vorgang ausgeführt werden soll, um die Ausgangsdaten in den gewünschten Zustand zu bringen.Migrations only considers model changes when determining what operation should be performed to get the seed data into the desired state. Daher können alle Änderungen an den Daten, die außerhalb der Migrationen durchgeführt werden, verloren gehen oder einen Fehler verursachen.Thus any changes to the data performed outside of migrations might be lost or cause an error.

So werden z. b. Seed-Daten für einen Blog in konfiguriert OnModelCreating :As an example, this will configure seed data for a Blog in OnModelCreating:

modelBuilder.Entity<Blog>().HasData(new Blog {BlogId = 1, Url = "http://sample.com"});

Um Entitäten hinzuzufügen, die eine Beziehung aufweisen, müssen die Fremdschlüssel Werte angegeben werden:To add entities that have a relationship the foreign key values need to be specified:

modelBuilder.Entity<Post>().HasData(
    new Post() { BlogId = 1, PostId = 1, Title = "First post", Content = "Test 1" });

Wenn der Entitätstyp über Eigenschaften im Schatten Zustand verfügt, kann eine anonyme Klasse verwendet werden, um die Werte bereitzustellen:If the entity type has any properties in shadow state an anonymous class can be used to provide the values:

modelBuilder.Entity<Post>().HasData(
    new { BlogId = 1, PostId = 2, Title = "Second post", Content = "Test 2" });

Eigene Entitäts Typen können auf ähnliche Weise als Seeding betrachtet werden:Owned entity types can be seeded in a similar fashion:

modelBuilder.Entity<Post>().OwnsOne(p => p.AuthorName).HasData(
    new { PostId = 1, First = "Andriy", Last = "Svyryd" },
    new { PostId = 2, First = "Diego", Last = "Vega" });

Weitere Informationen finden Sie im vollständigen Beispiel Projekt .See the full sample project for more context.

Nachdem die Daten dem Modell hinzugefügt wurden, sollten die Änderungen verwendet werden, um die Änderungen zu übernehmen.Once the data has been added to the model, migrations should be used to apply the changes.

Tipp

Wenn Sie Migrationen als Teil einer automatisierten Bereitstellung anwenden müssen, können Sie ein SQL-Skript erstellen , das vor der Ausführung in der Vorschau angezeigt werden kann.If you need to apply migrations as part of an automated deployment you can create a SQL script that can be previewed before execution.

Alternativ können Sie verwenden, context.Database.EnsureCreated() um eine neue Datenbank zu erstellen, die die Ausgangsdaten enthält, z. b. für eine Testdatenbank, oder wenn Sie den in-Memory-Anbieter oder eine nicht-beziehungsdatenbank verwenden.Alternatively, you can use context.Database.EnsureCreated() to create a new database containing the seed data, for example for a test database or when using the in-memory provider or any non-relation database. Beachten Sie Folgendes: Wenn die Datenbank bereits vorhanden ist, EnsureCreated() aktualisiert weder das Schema noch die Seed-Daten in der Datenbank.Note that if the database already exists, EnsureCreated() will neither update the schema nor seed data in the database. Bei relationalen Datenbanken sollten Sie nicht anrufen EnsureCreated() , wenn Sie beabsichtigen, Migrationen zu verwenden.For relational databases you shouldn't call EnsureCreated() if you plan to use Migrations.

Einschränkungen von modellseed-DatenLimitations of model seed data

Diese Art von Ausgangsdaten wird durch Migrationen verwaltet, und das Skript zum Aktualisieren der Daten, die bereits in der Datenbank vorhanden sind, muss generiert werden, ohne dass eine Verbindung mit der Datenbank hergestellt werden muss.This type of seed data is managed by migrations and the script to update the data that's already in the database needs to be generated without connecting to the database. Dies setzt einige Einschränkungen mit sich:This imposes some restrictions:

  • Der Primärschlüssel Wert muss angegeben werden, auch wenn er normalerweise von der Datenbank generiert wird.The primary key value needs to be specified even if it's usually generated by the database. Es wird verwendet, um Datenänderungen zwischen Migrationen zu erkennen.It will be used to detect data changes between migrations.
  • Zuvor Seeding Daten werden entfernt, wenn der Primärschlüssel in irgendeiner Weise geändert wird.Previously seeded data will be removed if the primary key is changed in any way.

Daher ist diese Funktion besonders nützlich für statische Daten, die sich außerhalb der Migrationen nicht ändern sollten, und ist nicht von anderen in der Datenbank abhängig, z. b. Postleitzahlen.Therefore this feature is most useful for static data that's not expected to change outside of migrations and does not depend on anything else in the database, for example ZIP codes.

Wenn in Ihrem Szenario eine der folgenden Szenarien enthalten ist, wird empfohlen, die im letzten Abschnitt beschriebene benutzerdefinierte Initialisierungs Logik zu verwenden:If your scenario includes any of the following it is recommended to use custom initialization logic described in the last section:

  • Temporäre Daten für TestsTemporary data for testing
  • Daten, die vom Daten Bank Status abhängenData that depends on database state
  • Große Daten (Seeding Daten werden in Migrations Momentaufnahmen aufgezeichnet, und große Daten können schnell zu sehr großen Dateien und eingeschränkter Leistung führen).Data that is large (seeding data gets captured in migration snapshots, and large data can quickly lead to huge files and degraded performance).
  • Daten, für die Schlüsselwerte benötigt werden, die von der Datenbank generiert werden müssen, einschließlich der Entitäten, die Alternative Schlüssel als Identität verwendenData that needs key values to be generated by the database, including entities that use alternate keys as the identity
  • Daten, die eine benutzerdefinierte Transformation erfordern (die nicht durch Wert Konvertierungenbehandelt wird), z. b. ein Kennwort-HashwertData that requires custom transformation (that is not handled by value conversions), such as some password hashing
  • Daten, für die Aufrufe externer API erforderlich sind, z. b. ASP.net Core Identitäts Rollen und Benutzer ErstellungData that requires calls to external API, such as ASP.NET Core Identity roles and users creation

Anpassung der manuellen MigrationManual migration customization

Beim Hinzufügen einer Migration werden die Änderungen an den mit angegebenen Daten HasData in Aufrufe von InsertData() , und transformiert UpdateData() DeleteData() .When a migration is added the changes to the data specified with HasData are transformed to calls to InsertData(), UpdateData(), and DeleteData(). Eine Möglichkeit, einige der Einschränkungen von HasData zu umgehen, besteht darin, diese Aufrufe oder benutzerdefinierten Vorgänge stattdessen manuell zur Migration hinzuzufügen.One way of working around some of the limitations of HasData is to manually add these calls or custom operations to the migration instead.

migrationBuilder.InsertData(
    table: "Blogs",
    columns: new[] { "Url" },
    values: new object[] { "http://generated.com" });

Benutzerdefinierte Initialisierungs LogikCustom initialization logic

Eine einfache und leistungsfähige Methode zum Durchführen von datenseeding ist die Verwendung von, DbContext.SaveChanges() bevor die Haupt Anwendungslogik mit der Ausführung beginnt.A straightforward and powerful way to perform data seeding is to use DbContext.SaveChanges() before the main application logic begins execution.

using (var context = new DataSeedingContext())
{
    context.Database.EnsureCreated();

    var testBlog = context.Blogs.FirstOrDefault(b => b.Url == "http://test.com");
    if (testBlog == null)
    {
        context.Blogs.Add(new Blog { Url = "http://test.com" });
    }
    context.SaveChanges();
}

Warnung

Der Seeding Code sollte nicht Teil der normalen App-Ausführung sein, da dies zu Parallelitäts Problemen führen kann, wenn mehrere Instanzen ausgeführt werden und die APP ebenfalls über die Berechtigung zum Ändern des Datenbankschemas verfügen würde.The seeding code should not be part of the normal app execution as this can cause concurrency issues when multiple instances are running and would also require the app having permission to modify the database schema.

Abhängig von den Einschränkungen der Bereitstellung kann der Initialisierungs Code auf unterschiedliche Weise ausgeführt werden:Depending on the constraints of your deployment the initialization code can be executed in different ways:

  • Lokales Ausführen der Initialisierungs-AppRunning the initialization app locally
  • Stellen Sie die Initialisierungs-App mit der Haupt-App bereit, indem Sie die Initialisierungs Routine aufrufen und die Initialisierungs-App deaktivieren oder entfernen.Deploying the initialization app with the main app, invoking the initialization routine and disabling or removing the initialization app.

Dies kann normalerweise mithilfe von Veröffentlichungs Profilenautomatisiert werden.This can usually be automated by using publish profiles.