Lernprogramm: Erfahren Sie mehr über erweiterte Szenarien – ASP.NET MVC mit EF Core
Im vorherigen Tutorial haben Sie die „Tabelle pro Hierarchie“-Vererbung implementiert. In diesem Lernprogramm werden mehrere Themen vorgestellt, die hilfreich sind, wenn Sie über die Grundlagen der Entwicklung von ASP.NET Core-Webanwendungen hinausgehen, die Entity Framework Core verwenden.
In diesem Tutorial:
- Ausführen von rohen SQL-Abfragen
- Aufrufen einer Abfrage zum Zurückgeben von Entitäten
- Aufrufen einer Abfrage zum Zurückgeben von Typen
- Aufrufen einer Aktualisierungsabfrage
- Untersuchen von SQL-Abfragen
- Erstellen einer Abstraktionsebene
- Informationen zur automatischen Änderungserkennung
- Informationen zu EF Core Quellcode und Entwicklungsplänen
- Erfahren Sie, wie Sie dynamische LINQ verwenden, um Code zu vereinfachen
Voraussetzungen
Ausführen von rohen SQL-Abfragen
Einer der Vorteile der Verwendung von Entity Framework besteht darin, dass der Code nicht zu eng mit einer bestimmten Methode zum Speichern von Daten verbunden wird. Dadurch werden SQL-Abfragen und -Befehle für Sie generiert, sodass Sie sie nicht selbst schreiben müssen. Es gibt jedoch außergewöhnliche Szenarien, wenn Sie bestimmte SQL-Abfragen ausführen müssen, die Sie manuell erstellt haben. In diesen Szenarien enthält die Entity Framework Code First-API Methoden, mit denen Sie SQL-Befehle direkt an die Datenbank übergeben können. Sie haben die folgenden Optionen in EF Core 1.0:
Verwenden Sie die
DbSet.FromSql
-Methode für Abfragen, die Entitätstypen zurückgeben. Die Typen der zurückgegebenen Objekte müssen den Erwartungen desDbSet
-Objekts entsprechen, und sie werden automatisch vom Datenbankkontext nachverfolgt, außer wenn Sie die Überwachung deaktivieren.Verwenden Sie die
Database.ExecuteSqlCommand
für Nicht-Abfragebefehle.
Wenn Sie eine Abfrage ausführen müssen, die Typen zurückgibt, die keine Entitäten sind, können Sie ADO.NET mit der datenbankverbindung verwenden, die von EF bereitgestellt wird. Die zurückgegebenen Daten werden nicht vom Datenbankkontext nachverfolgt, auch wenn Sie diese Methode zum Abrufen von Entitätstypen verwenden.
Wie immer zutrifft, wenn Sie SQL-Befehle in einer Webanwendung ausführen, müssen Sie Vorsichtsmaßnahmen ergreifen, um Ihre Website vor SQL-Einfügungsangriffen zu schützen. Eine Möglichkeit hierfür ist die Verwendung parametrisierter Abfragen, um sicherzustellen, dass von einer Webseite übermittelte Zeichenfolgen nicht als SQL-Befehle interpretiert werden können. In diesem Lernprogramm verwenden Sie parametrisierte Abfragen, wenn Sie Benutzereingaben in eine Abfrage integrieren.
Aufrufen einer Abfrage zum Zurückgeben von Entitäten
Die DbSet<TEntity>
Klasse stellt eine Methode bereit, mit der Sie eine Abfrage ausführen können, die eine Entität vom Typ TEntity
zurückgibt. Um zu sehen, wie dies funktioniert, ändern Sie den Code in der Details
-Funktion des Department Controllers.
Ersetzen Sie, wie im folgenden hervorgehobenen Code gezeigt, in DepartmentsController.cs
in der Details
-Methode den Code, der eine Abteilung mit einem FromSql
-Methodenaufruf abruft:
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
string query = "SELECT * FROM Department WHERE DepartmentID = {0}";
var department = await _context.Departments
.FromSql(query, id)
.Include(d => d.Administrator)
.AsNoTracking()
.FirstOrDefaultAsync();
if (department == null)
{
return NotFound();
}
return View(department);
}
Um zu überprüfen, ob der neue Code ordnungsgemäß funktioniert, wählen Sie die Registerkarte Abteilungen aus, und Details für eine der Abteilungen.
Aufrufen einer Abfrage zum Zurückgeben von Typen
Zuvor haben Sie ein Studentenstatistikraster für die Seite "Über" erstellt, auf dem die Anzahl der Studenten für jedes Anmeldedatum angezeigt wurde. Sie haben die Daten aus der Entitätsmenge 'Schüler' (_context.Students
) abgerufen und LINQ verwendet, um die Ergebnisse in eine Liste von EnrollmentDateGroup
-Ansichtsmodellobjekten zu überführen. Angenommen, Sie möchten die SQL selbst schreiben, anstatt LINQ zu verwenden. Dazu müssen Sie eine SQL-Abfrage ausführen, die einen anderen Wert als Entitätsobjekte zurückgibt. In EF Core 1.0 können Sie dazu ADO.NET Code schreiben und die Datenbankverbindung aus EF abrufen.
Ersetzen Sie in HomeController.cs
die About
-Methode durch den folgenden Code:
public async Task<ActionResult> About()
{
List<EnrollmentDateGroup> groups = new List<EnrollmentDateGroup>();
var conn = _context.Database.GetDbConnection();
try
{
await conn.OpenAsync();
using (var command = conn.CreateCommand())
{
string query = "SELECT EnrollmentDate, COUNT(*) AS StudentCount "
+ "FROM Person "
+ "WHERE Discriminator = 'Student' "
+ "GROUP BY EnrollmentDate";
command.CommandText = query;
DbDataReader reader = await command.ExecuteReaderAsync();
if (reader.HasRows)
{
while (await reader.ReadAsync())
{
var row = new EnrollmentDateGroup { EnrollmentDate = reader.GetDateTime(0), StudentCount = reader.GetInt32(1) };
groups.Add(row);
}
}
reader.Dispose();
}
}
finally
{
conn.Close();
}
return View(groups);
}
Fügen Sie eine Using-Anweisung hinzu:
using System.Data.Common;
Führen Sie die App aus, und wechseln Sie zur Seite "Info". Es zeigt die gleichen Daten an wie zuvor.
Aufrufen einer Aktualisierungsabfrage
Angenommen, Contoso University-Administratoren möchten globale Änderungen in der Datenbank ausführen, z. B. die Anzahl der Credits für jeden Kurs ändern. Wenn die Universität über eine große Anzahl von Kursen verfügt, wäre es ineffizient, sie als Entitäten abzurufen und einzeln zu ändern. In diesem Abschnitt implementieren Sie eine Webseite, mit der der Benutzer einen Faktor angeben kann, um den die Anzahl der Credits für alle Kurse geändert werden soll, und Sie nehmen die Änderung vor, indem Sie eine SQL UPDATE-Anweisung ausführen. Die Webseite sieht wie in der folgenden Abbildung aus:
Fügen Sie in CoursesController.cs
UpdateCourseCredits-Methoden für HttpGet und HttpPost hinzu:
public IActionResult UpdateCourseCredits()
{
return View();
}
[HttpPost]
public async Task<IActionResult> UpdateCourseCredits(int? multiplier)
{
if (multiplier != null)
{
ViewData["RowsAffected"] =
await _context.Database.ExecuteSqlCommandAsync(
"UPDATE Course SET Credits = Credits * {0}",
parameters: multiplier);
}
return View();
}
Wenn der Controller eine HttpGet-Anforderung verarbeitet, wird nichts in ViewData["RowsAffected"]
zurückgegeben, und die Ansicht zeigt ein leeres Textfeld und eine Schaltfläche zum Absenden an, wie in der vorherigen Abbildung dargestellt.
Wenn auf die Schaltfläche Aktualisieren geklickt wird, wird die HttpPost-Methode aufgerufen, und der Multiplikator hat den Wert in das Textfeld eingegeben. Der Code führt dann das SQL aus, das Kurse aktualisiert und die Anzahl der betroffenen Zeilen an die Ansicht in ViewData
zurückgibt. Wenn die Ansicht einen RowsAffected
Wert abruft, wird die Anzahl der aktualisierten Zeilen angezeigt.
Klicken Sie im Projektmappen-Explorermit der rechten Maustaste auf den Ordner Ansichten/Kurse, und klicken Sie dann auf Hinzufügen > Neues Element.
Klicken Sie im Dialogfeld Neues Element hinzufügen unter Installiert im linken Bereich auf ASP.NET Core und anschließend auf Razor-Ansicht und benennen Sie die neue Ansicht UpdateCourseCredits.cshtml
.
Ersetzen Sie in Views/Courses/UpdateCourseCredits.cshtml
den Vorlagencode durch den folgenden Code:
@{
ViewBag.Title = "UpdateCourseCredits";
}
<h2>Update Course Credits</h2>
@if (ViewData["RowsAffected"] == null)
{
<form asp-action="UpdateCourseCredits">
<div class="form-actions no-color">
<p>
Enter a number to multiply every course's credits by: @Html.TextBox("multiplier")
</p>
<p>
<input type="submit" value="Update" class="btn btn-default" />
</p>
</div>
</form>
}
@if (ViewData["RowsAffected"] != null)
{
<p>
Number of rows updated: @ViewData["RowsAffected"]
</p>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
Führen Sie die UpdateCourseCredits
-Methode aus, indem Sie die Registerkarte Kurse auswählen und dann "/UpdateCourseCredits" am Ende der URL in der Adressleiste des Browsers hinzufügen (z. B. http://localhost:5813/Courses/UpdateCourseCredits
). Geben Sie eine Zahl in das Textfeld ein:
Klicken Sie auf Aktualisieren. Die Anzahl der betroffenen Zeilen wird angezeigt:
Klicken Sie auf Zurück zur Liste, um die Liste der Kurse mit der überarbeiteten Anzahl der Credits anzuzeigen.
Beachten Sie, dass der Produktionscode sicherstellen würde, dass Aktualisierungen immer zu gültigen Daten führen. Der hier gezeigte vereinfachte Code könnte die Anzahl der Gutschriften so weit multiplizieren, dass sie größer als 5 werden. (Die Credits
-Eigenschaft weist ein [Range(0, 5)]
Attribut auf.) Die Aktualisierungsabfrage funktionierte, aber die ungültigen Daten könnten zu unerwarteten Ergebnissen in anderen Teilen des Systems führen, die davon ausgehen, dass die Anzahl der Gutschriften 5 oder weniger beträgt.
Weitere Informationen zu unformatierten SQL-Abfragen finden Sie unter raw SQL Queries.
Untersuchen von SQL-Abfragen
Manchmal ist es hilfreich, die tatsächlichen SQL-Abfragen anzuzeigen, die an die Datenbank gesendet werden. Integrierte Protokollierungsfunktion für ASP.NET Core wird automatisch von EF Core verwendet, um Protokolle zu schreiben, die SQL für Abfragen und Updates enthalten. In diesem Abschnitt finden Sie einige Beispiele für die SQL-Protokollierung.
Öffnen Sie StudentsController.cs
, und legen Sie in der Details
-Methode einen Haltepunkt für die if (student == null)
-Anweisung fest.
Führen Sie die App im Debugmodus aus, und wechseln Sie zur Seite "Details" für einen Kursteilnehmer.
Wechseln Sie zum Ausgabe-Fenster, zeigen Sie die Debugausgabe an, und Sie sehen die Abfrage:
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (56ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
SELECT TOP(2) [s].[ID], [s].[Discriminator], [s].[FirstName], [s].[LastName], [s].[EnrollmentDate]
FROM [Person] AS [s]
WHERE ([s].[Discriminator] = N'Student') AND ([s].[ID] = @__id_0)
ORDER BY [s].[ID]
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (122ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
SELECT [s.Enrollments].[EnrollmentID], [s.Enrollments].[CourseID], [s.Enrollments].[Grade], [s.Enrollments].[StudentID], [e.Course].[CourseID], [e.Course].[Credits], [e.Course].[DepartmentID], [e.Course].[Title]
FROM [Enrollment] AS [s.Enrollments]
INNER JOIN [Course] AS [e.Course] ON [s.Enrollments].[CourseID] = [e.Course].[CourseID]
INNER JOIN (
SELECT TOP(1) [s0].[ID]
FROM [Person] AS [s0]
WHERE ([s0].[Discriminator] = N'Student') AND ([s0].[ID] = @__id_0)
ORDER BY [s0].[ID]
) AS [t] ON [s.Enrollments].[StudentID] = [t].[ID]
ORDER BY [t].[ID]
Sie werden hier etwas bemerken, das Sie möglicherweise überrascht: Die SQL wählt bis zu 2 Zeilen (TOP(2)
) aus der Tabelle "Person" aus. Die SingleOrDefaultAsync
-Methode wird nicht nach einer Zeile auf dem Server aufgelöst. Hier ist der Grund:
- Wenn die Abfrage mehrere Zeilen zurückgibt, gibt die Methode NULL zurück.
- Um festzustellen, ob die Abfrage mehrere Zeilen zurückgeben würde, muss EF überprüfen, ob sie mindestens 2 zurückgibt.
Beachten Sie, dass Sie nicht den Debugmodus verwenden und an einem Haltepunkt anhalten müssen, um die Protokollierungsausgabe im Ausgabe-Fenster anzuzeigen. Es ist nur eine bequeme Möglichkeit, die Protokollierung an dem Punkt zu beenden, an dem Sie die Ausgabe betrachten möchten. Wenn Sie dies nicht tun, wird die Protokollierung fortgesetzt, und Sie müssen zurück scrollen, um die teile zu finden, an denen Sie interessiert sind.
Erstellen einer Abstraktionsebene
Viele Entwickler schreiben Code, um das Repository und die Arbeitsmustereinheit als Wrapper um Code zu implementieren, der mit Entity Framework funktioniert. Diese Muster sollen eine Abstraktionsebene zwischen der Datenzugriffsschicht und der Geschäftslogikebene einer Anwendung erstellen. Die Implementierung dieser Muster kann dazu beitragen, Ihre Anwendung vor Änderungen im Datenspeicher zu isolieren und automatisierte Komponententests oder testgesteuerte Entwicklung (TDD) zu vereinfachen. Das Schreiben von zusätzlichem Code zum Implementieren dieser Muster ist jedoch nicht immer die beste Wahl für Anwendungen, die EF verwenden, aus mehreren Gründen:
Die EF-Kontextklasse selbst isoliert Ihren Code vor datenspeicherspezifischem Code.
Die EF-Kontextklasse kann als Arbeitseinheit für Datenbankaktualisierungen fungieren, die Sie mit EF verwenden.
EF enthält Features für die Implementierung von TDD, ohne Repositorycode zu schreiben.
Informationen zum Implementieren des Repositorys und der Arbeitsmustereinheit finden Sie unter der Entity Framework 5-Version dieser Lernprogrammreihe.
Entity Framework Core implementiert einen In-Memory-Datenbankanbieter, der für Tests verwendet werden kann. Weitere Informationen finden Sie unter Test with InMemory.
Automatische Änderungserkennung
Das Entity Framework bestimmt, wie sich eine Entität geändert hat (und daher welche Aktualisierungen an die Datenbank gesendet werden müssen), indem die aktuellen Werte einer Entität mit den ursprünglichen Werten verglichen werden. Die ursprünglichen Werte werden gespeichert, wenn die Entität abgefragt oder angefügt wird. Einige der Methoden, die die automatische Änderungserkennung verursachen, sind die folgenden:
DbContext.SaveChanges
DbContext.Entry
ChangeTracker.Entries
Wenn Sie eine große Anzahl von Entitäten nachverfolgen und eine dieser Methoden mehrmals in einer Schleife aufrufen, erhalten Sie möglicherweise erhebliche Leistungsverbesserungen, indem Sie die automatische Änderungserkennung mit der eigenschaft ChangeTracker.AutoDetectChangesEnabled
vorübergehend deaktivieren. Zum Beispiel:
_context.ChangeTracker.AutoDetectChangesEnabled = false;
EF Core Quellcode und Entwicklungspläne
Die Entity Framework Core-Quelle befindet sich auf https://github.com/dotnet/efcore. Das EF Core-Repository enthält über Nacht erstellte Builds, Problemverfolgung, Featurespezifikationen, Notizen der Designbesprechungen und die Roadmap für künftige Entwicklungen. Sie können Fehler melden oder finden und beitragen.
Obwohl der Quellcode geöffnet ist, wird Entity Framework Core vollständig als Microsoft-Produkt unterstützt. Das Microsoft Entity Framework-Team behält die Kontrolle darüber, welche Beiträge akzeptiert werden, und testet alle Codeänderungen, um die Qualität der einzelnen Versionen sicherzustellen.
Reverse Engineering aus der bestehenden Datenbank
Verwenden Sie zum Reverse Engineering eines Datenmodells, einschließlich von Entitätsklassen aus einer vorhandenen Datenbank, den Befehl scaffold-dbcontext. Lesen Sie das Tutorial Erste Schritte.
Verwenden von dynamischem LINQ zum Vereinfachen von Code
Das dritte Tutorial dieser Reihe zeigt, wie Sie LINQ-Code schreiben, indem Sie eine Hartcodierung der Spaltennamen in einer switch
-Anweisung durchführen. Mit zwei Spalten zur Auswahl funktioniert dies hervorragend, aber wenn Sie viele Spalten zur Verfügung haben, könnte der Code ausführlich werden. Um dieses Problem zu beheben, können Sie die EF.Property
-Methode verwenden, um den Namen der Eigenschaft als Zeichenfolge anzugeben. Um diesen Ansatz auszuprobieren, ersetzen Sie die Index
-Methode im StudentsController
durch den folgenden Code.
public async Task<IActionResult> Index(
string sortOrder,
string currentFilter,
string searchString,
int? pageNumber)
{
ViewData["CurrentSort"] = sortOrder;
ViewData["NameSortParm"] =
String.IsNullOrEmpty(sortOrder) ? "LastName_desc" : "";
ViewData["DateSortParm"] =
sortOrder == "EnrollmentDate" ? "EnrollmentDate_desc" : "EnrollmentDate";
if (searchString != null)
{
pageNumber = 1;
}
else
{
searchString = currentFilter;
}
ViewData["CurrentFilter"] = searchString;
var students = from s in _context.Students
select s;
if (!String.IsNullOrEmpty(searchString))
{
students = students.Where(s => s.LastName.Contains(searchString)
|| s.FirstMidName.Contains(searchString));
}
if (string.IsNullOrEmpty(sortOrder))
{
sortOrder = "LastName";
}
bool descending = false;
if (sortOrder.EndsWith("_desc"))
{
sortOrder = sortOrder.Substring(0, sortOrder.Length - 5);
descending = true;
}
if (descending)
{
students = students.OrderByDescending(e => EF.Property<object>(e, sortOrder));
}
else
{
students = students.OrderBy(e => EF.Property<object>(e, sortOrder));
}
int pageSize = 3;
return View(await PaginatedList<Student>.CreateAsync(students.AsNoTracking(),
pageNumber ?? 1, pageSize));
}
Danksagungen
Tom Dykstra und Rick Anderson (Twitter @RickAndMSFT)) schrieben dieses Lernprogramm. Rowan Miller, Diego Vega und andere Mitglieder des Entity Framework-Teams unterstützten Codeüberprüfungen und halfen beim Debuggen von Problemen, die während des Schreibens von Code für die Lernprogramme entstanden sind. John Parente und Paul Goldman arbeiteten an der Aktualisierung des Lernprogramms für ASP.NET Core 2.2.
Häufige Fehler beheben
ContosoUniversity.dll wird von einem anderen Prozess verwendet
Fehlermeldung:
Konnte '...bin\Debug\netcoreapp1.0\ContosoUniversity.dll' for writing -- 'The process cannot access the file '...\bin\Debug\netcoreapp1.0\ContosoUniversity.dll' nicht öffnen, weil es von einem anderen Prozess verwendet wird.
Lösung:
Beenden Sie die Website in IIS Express. Wechseln Sie zur Windows-Taskleiste, suchen Sie IIS Express, klicken Sie mit der rechten Maustaste auf das Symbol, wählen Sie den Standort Contoso University aus, und klicken Sie dann auf Website beenden.
Gerüstete Migration ohne Code in Up-und Down-Methoden
Mögliche Ursache:
Die EF CLI-Befehle schließen und speichern nicht automatisch Codedateien. Wenn Sie beim Ausführen des Befehls migrations add
nicht gespeicherte Änderungen haben, findet EF ihre Änderungen nicht.
Lösung:
Führen Sie den Befehl migrations remove
aus, speichern Sie die Codeänderungen, und führen Sie den befehl migrations add
erneut aus.
Fehler beim Ausführen der Datenbankaktualisierung
Es ist möglich, andere Fehler beim Vornehmen von Schemaänderungen in einer Datenbank mit vorhandenen Daten zu erhalten. Wenn Sie Migrationsfehler erhalten, die Sie nicht beheben können, können Sie entweder den Datenbanknamen in der Verbindungszeichenfolge ändern oder die Datenbank löschen. Bei einer neuen Datenbank gibt es keine zu migrierende Daten, und der Befehl "Update-Datenbank" wird mit größerer Wahrscheinlichkeit ohne Fehler abgeschlossen.
Der einfachste Ansatz besteht darin, die Datenbank in appsettings.json
umzubenennen. Beim nächsten Ausführen von database update
wird eine neue Datenbank erstellt.
Klicken Sie zum Löschen einer Datenbank in SSOX mit der rechten Maustaste auf die Datenbank, klicken Sie auf Löschen, und wählen Sie dann im Dialogfeld Datenbank löschen die Option Vorhandene Verbindungen schließen aus, und klicken Sie auf OK.
Führen Sie den Befehl database drop
CLI aus, um eine Datenbank mithilfe der CLI zu löschen:
dotnet ef database drop
Fehler beim Suchen der SQL Server-Instanz
Fehlermeldung:
Beim Herstellen einer Verbindung mit SQL Server ist ein netzwerkbezogener oder instanzspezifischer Fehler aufgetreten. Der Server wurde nicht gefunden oder war nicht zugänglich. Vergewissern Sie sich, dass der Instanzname korrekt ist und SQL Server so konfiguriert ist, dass Remoteverbindungen zulässig sind. (Anbieter: SQL-Netzwerkschnittstellen, Fehler: 26 – Fehler beim Auffinden des angegebenen Servers/der Instanz)
Lösung:
Überprüfen Sie die Verbindungszeichenfolge. Wenn Sie die Datenbankdatei manuell gelöscht haben, ändern Sie den Namen der Datenbank in der Konstruktionszeichenfolge, um mit einer neuen Datenbank zu beginnen.
Code abrufen
Herunterladen oder Anzeigen der abgeschlossenen Anwendung.
Weitere Ressourcen
Weitere Informationen zu EF Corefinden Sie in der Entity Framework Core-Dokumentation. Ein Buch ist auch verfügbar: Entity Framework Core in Action.
Informationen zum Bereitstellen einer Webanwendung finden Sie unter Host und Bereitstellen von ASP.NET Core.
Informationen zu anderen Themen im Zusammenhang mit ASP.NET Core MVC, z. B. Authentifizierung und Autorisierung, finden Sie unter Übersicht über ASP.NET Core-.
Anleitungen zum Erstellen einer zuverlässigen, sicheren, leistungsfähigen, testbaren und skalierbaren ASP.NET Core-App finden Sie unter Enterprise Web App-Muster. Eine vollständige Beispielweb-App zur Produktionsqualität, die die Muster implementiert, ist verfügbar.
Nächste Schritte
In diesem Tutorial:
- Ausgeführte rohe SQL-Abfragen
- Haben Sie eine Abfrage zum Zurückgeben von Entitäten aufgerufen
- Haben Sie eine Abfrage zum Zurückgeben anderer Typen aufgerufen
- Als Aktualisierungsabfrage bezeichnet
- Untersuchte SQL-Abfragen
- Erstellt eine Abstraktionsebene
- Erlerntes über automatische Änderungserkennung
- Erfahren Sie mehr über EF Core Quellcode und Entwicklungspläne
- Erfahren Sie, wie Sie dynamische LINQ verwenden, um Code zu vereinfachen
Dies schließt diese Reihe von Lernprogrammen zur Verwendung von Entity Framework Core in einer ASP.NET Core MVC-Anwendung ab. Diese Serie hat eine neue Datenbank verwendet. Eine Alternative besteht darin, ein Modell aus einer vorhandenen Datenbank zurückzuentwickeln.