Entity Framework Core ist eine populäre ORM (Object-Relational Mapper) für .NET-Anwendungen, die Entwicklern erlaubt, mit Datenbanken über .NET-Objekte zu arbeiten. Es kann mit vielen Arten von Datenbanken verwendet werden, einschließlich MongoDB.
In diesem Artikel lernen Sie, wie Sie Entity Framework Core mit MongoDB verwenden können. Dieser Artikel behandelt die Grundlagen, erklärt die Vorteile und bietet ein Schritt-für-Schritt-Leitfaden. Egal, ob Sie neu bei MongoDB oder Entity Framework Core sind oder lediglich darauf drängen, diese Tools in Ihren .NET-Projekten zu integrieren, dieser Leitfaden wird Ihnen helfen, den Abstand zwischen relationalen und NoSQL-Datenbanken zu überbrücken.
Der Artikel beginnt mit einer kurzen Einführung in MongoDB sowie in Microsofts Entity Framework Core. Danach geht es darum, den MongoDB EF Core Provider zu verwenden. Nachdem Sie technische Details mit einigen grundlegenden Beispielen durchlaufen haben, erstellen Sie ein komplettes Projekt mit MongoB und Entity Framework Core, um zu sehen, wie alle Teile zusammenarbeiten. Das Projekt wird MongoDB Atlas-Beispieldaten verwenden, um ein Restaurantreservierungssystem zu erstellen.
Es gibt auch eine Videoversion dieses Artikels, die Sie auf dem freeCodeCamp.org YouTube-Kanal anschauen können.
Einführung in MongoDB
MongoDB ist eine populäre NoSQL-Datenbank, die für die Behandlung hoher Datenmengen und hohe Leistung, Skalierbarkeit und Flexibilität konzipiert wurde. Im Gegensatz zu traditionellen relationalen Datenbanken speichert MongoDB Daten in flexiblen, JSON-ähnlichen Dokumenten. Dieser dokumentenorientierte Ansatz ermöglicht die Speicherung komplexer Datenstrukturen in einer natürlicheren und intuitiven Weise.
In MongoDB werden Daten in Sammlungen gespeichert, die den Tabellen in relationalen Datenbanken ähneln, jedoch ohne festen Schema. Dies bedeutet, dass Sie in derselben Sammlung Dokumente mit verschiedenen Strukturen haben können. Diese Flexibilität ist eine der wichtigsten Vorteile der Verwendung von MongoDB, insbesondere beim Umgang mit unstrukturierten oder halbstrukturierten Daten.
Lassen Sie uns ein Beispiel eines MongoDB-Dokuments anschauen. Stellen Sie sich vor, wir haben eine Sammlung namens users
, die Informationen über Benutzer in einer Anwendung speichert. Hier ist was ein typisches Dokument vielleicht aussehen könnte:
{
"_id": "12345",
"name": "John Doe",
"email": "[email protected]",
"age": 30,
"address": {
"street": "123 Main St",
"city": "Anytown",
"state": "CA",
"zip": "12345"
},
"hobbies": ["reading", "travelling", "coding"]
}
In diesem Dokument haben wir verschiedene Felder wie name
, email
, age
und address
. Das Feld address
selbst ist ein eingebettetes Dokument, das mehrere Unterfelder wie street
, city
, state
und zip
enthält. Zusätzlich ist das Feld hobbies
ein Array von String-Werten.
Obwohl dies aussieht wie JSON, speichert MongoDB Daten in einer binären Formatierung namens BSON (Binary JSON). BSON erweitert das JSON-Modell, um zusätzliche Datentypen bereitzustellen, wie z.B. Integer, Floats, Daten und binäre Daten. Dieses binäre Format ist für Leistung und Flexibilität optimiert, was MongoDB dazu befähigt, Daten effizient zu speichern und abzurufen.
Eine weitere wichtige Funktion von MongoDB ist die horizontale Skalierung. Dies bedeutet, dass Sie Ihre Daten auf mehreren Servern verteilen können, was die Verwaltung großer Datensets einfacher macht und hohe Verfügbarkeit gewährleistet. MongoDB unterstützt auch reiche Abfragen, Indexierung und Aggregation, making it a powerful tool for a wide range of applications.
Zum Beispiel können Sie eine Abfrage durchführen, um alle Benutzer zu finden, die in einer bestimmten Stadt leben:
db.users.find({ "address.city": "Anytown" })
Oder Sie finden Nutzer, die eine bestimmte Hobby haben:
db.users.find({ "hobbies": "coding" })
MongoDB wird in verschiedenen Branchen verwendet, von E-Commerce und Inhaltsverwaltung bis zu Echtzeitanalyse und Internet der Dinge (IoT)-Anwendungen. Seine Flexibilität und Skalierbarkeit machen ihn zu einer hervorragenden Wahl für moderne Anwendungen, die vielfältige und dynamische Daten verarbeiten müssen.
Nun, da wir einen grundlegenden Überblick über was MongoDB ist und warum es populär ist, lassen Sie uns zu einem weiteren wichtigen Werkzeug in unserer Tech-Stack gehen: Microsofts Entity Framework Core.
Einführung in Microsofts Entity Framework Core
Entity Framework Core, oft abgekürzt als EF Core, ist ein moderner Objekt-Datenbank-Mapper für .NET. Es ermöglicht Entwicklern, mit einer Datenbank mit .NET-Objekten zu arbeiten und reduziert die Notwendigkeit, die meisten Datenbankzugriffscode zu schreiben.
EF Core ist eine leichte, erweiterbare und plattformübergreifende Version der populären Entity Framework (EF) Datenbanktechnologie. Es unterstützt eine Vielzahl an Datenbankmotoren, einschließlich SQL Server, SQLite und MongoDB.
Eine der Hauptvorteile der Verwendung von EF Core ist, dass Entwickler mit Daten in einer intuitiven und objektorientierten Weise arbeiten können. Statt von rohen SQL-Abfragen zu schreiben, können Sie mit Ihrer Datenbank über LINQ (Language Integrated Query) und stark typisierte Klassen interagieren.
Lassen Sie uns einfach einen grundlegenden Beispiel anschauen. Stellen Sie sich vor, wir haben eine Product
-Klasse:
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
Dies ist recht einfach mit nur drei Feldern. Mit EF Core können Sie einen Context-Klasse erstellen, die eine Sitzung mit der Datenbank repräsentiert und ein DbSet
für jedenEntitätstyp, den Sie abfragen oder speichern möchten, enthält:
public class AppDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.Use<Your_SQL_Database_function>("YourConnectionStringHere");
}
}
Dieser Code definiert eine Klasse namens AppDbContext
, die von Entity Framework Core’s DbContext
-Klasse erbt. Diese Klasse wird verwendet, um mit der Datenbank zu interagieren. Innerhalb dieser Klasse gibt es eine DbSet<Product>
-Eigenschaft namens Products
, die eine Sammlung von Product
-Entitäten repräsentiert und auf eine Tabelle namens Products
in der Datenbank abbildet. Der OnConfiguring
-Methode wird überschrieben, um die Datenbankverbindung zu konfigurieren. Sie können verschiedene Datenbanken als Datenbankanbieter angeben. Diese Methode verwendet ein optionsBuilder
, um die Verbindung mit einem Platzhalter für die tatsächliche Datenbankverbindungstrings zu setzen. Dieser Verbindungstrunkt sollte offensichtlich mit der tatsächlichen Verbindungstrings ausgetauscht werden, der die notwendigen Details enthält, um mit der Datenbank zu verbinden. Wenn Sie eine Instanz von AppDbContext
in der Anwendung erzeugen, nutzt sie diese Konfiguration, um Operationen wie Abfragen oder Speichern von Product
-Entitäten in der Products
-Tabelle durchzuführen.
Mit dieser Einrichtung können Sie CRUD- (Create, Read, Update, Delete)-Operationen mit EF Core durchführen. Zum Beispiel können Sie mit diesem Code ein neues Produkt in die Datenbank einfügen.
using (var context = new AppDbContext())
{
var product = new Product { Name = "Laptop", Price = 999.99M };
context.Products.Add(product);
context.SaveChanges();
}
Dieser Code zeigt, wie ein neues Produkt in die Datenbank mithilfe von Entity Framework Core hinzugefügt wird. Es wird eine Instanz von AppDbContext
erstellt, und innerhalb dieses Kontextes wird ein neues Produkt
-Objekt mit dem Namen „Laptop“ und dem Preis 999,99 erstellt. Dieses neue Produkt wird dann zur Produkte
-Sammlung, die von AppDbContext
verwaltet wird, hinzugefügt. Schließlich wird die Methode SaveChanges
aufgerufen, um die Änderungen in die Datenbank zu speichern, was die tatsächliche Einfügung des neuen Produkts in die Produkte
-Tabelle bedeutet.
Um Produkte abzufragen, kannst du LINQ verwenden:
using (var context = new AppDbContext())
{
var products = context.Products.Where(p => p.Price > 500).ToList();
foreach (var product in products)
{
Console.WriteLine($"Product: {product.Name}, Price: {product.Price}");
}
}
Dieser Code zeigt, wie die Datenbank mit Entity Framework Core abgefragt wird. Es wird eine Instanz von AppDbContext
erstellt, und innerhalb dieses Kontextes wird eine Abfrage durchgeführt, um alle Produkte mit einem Preis von mehr als 500 zu erhalten. Die Ergebnisse werden in einer Liste namens produkte
gespeichert. Anschließend wird in einem Loop durch jedes Produkt in der Liste iteriert, und der Name und der Preis jedes Produkts werden auf der Konsole ausgegeben.
EF Core übernimmt die Übersetzung dieser LINQ-Abfragen in die entsprechenden SQL-Befehle für Ihre Datenbank, was die Datenzugriffskonzepte einfacher und wartbarer macht.
EF Core unterstützt auch fortgeschrittene Features wie Change Tracking, Lazy Loading und Migrations, die Ihnen helfen, die Datenbankschemacheichtengebnissezeit zu verwalten.
In Zusammenfassung vereinfacht EF Core den Zugriff auf Daten in .NET-Anwendungen, indem Sie mit .NET-Objekten und LINQ auf Ihre Daten arbeiten können. Seine Unterstützung für mehrere Datenbankengines und seine Erweiterbarkeit machen ihn zu einer vielseitigen Wahl für eine Vielzahl von Anwendungen.
Als nächstes sehen wir, wie der MongoDB EF Core Provider die Lücke zwischen MongoDB und EF Core überbrückt und es uns ermöglicht, die vertrauten EF Core-Muster mit einer MongoDB-Datenbank zu verwenden.
Wie der MongoDB EF Core Provider die Lücke überbrückt
Der MongoDB Entity Framework Core Provider ist ein Tool, mit dem Entwickler MongoDB mit Entity Framework Core (EF Core) verwenden können. Es kombiniert die Flexibilität von MongoDB mit der vertrauten API und den Designmustern von EF Core. Dieser Provider ermöglicht es Ihnen, mit MongoDB zu arbeiten und dabei die gleichen codebasierten und LINQ-Abfrage-Methoden zu verwenden, die Sie auch bei relationalen Datenbanken verwenden würden. Dadurch wird die Entwicklung vereinfacht und die Einarbeitungszeit für diejenigen, die bereits mit EF Core vertraut sind, reduziert.
Der MongoDB EF Core Provider überbrückt die Lücke zwischen MongoDB und EF Core, indem er grundlegende CRUD-Operationen, LINQ-Abfragen und eingebettete Dokumente sowie andere Funktionen unterstützt. Hier sind einige wichtige Möglichkeiten:
-
Code-First-Workflows: Sie können Ihre Datenmodelle in C# definieren und EF Core verwenden, um das MongoDB-Schema zu generieren, anstatt mit dem Datenbankschema zu beginnen und Code daraus zu generieren. Dies ist besonders nützlich für Entwickler, die ihre Datenbankstruktur lieber über Code verwalten möchten.
-
CRUD-Operationen: Der Anbieter unterstützt grundlegende Schreiben, Lesen, Aktualisieren und Löschen von Datenbankoperationen. Zum Beispiel können Sie mit demselben Code, wie wir früher gesehen haben, eine neue Datensatz zu der Datenbank hinzufügen:
using (var context = new AppDbContext()) { var product = new Product { Name = "Laptop", Price = 999.99M }; context.Products.Add(product); context.SaveChanges(); }
-
LINQ-Abfrageunterstützung: Sie können LINQ verwenden, um Abfragen an MongoDB durchzuführen, was es Ihnen ermöglicht, Ihr bestehendes Wissen über C# und .NET einzusetzen, um mit der Datenbank zu interagieren.
using (var context = new AppDbContext()) { var products = context.Products.Where(p => p.Price > 500).ToList(); foreach (var product in products) { Console.WriteLine($"Product: {product.Name}, Price: {product.Price}"); } }
-
Änderungsverfolgung: Die Änderungsverfolgungsmöglichkeiten von EF Core werden unterstützt, was die automatische Erkennung und Speicherung von Änderungen, die an Ihren Datenentitäten vorgenommen werden, ermöglicht.
-
Eingebettete Dokumente: Der Anbieter unterstützt eingebettete Dokumente, was es Ihnen erlaubt, verwandte Daten innerhalb eines einzigen Dokuments zu speichern, was ein häufiges Muster in MongoDB ist.
-
Klassen-Kartierung und Serialisierung: Ihre C#-Klassen werden auf MongoDB-Sammlungen abgebildet, mit Unterstützung für verschiedene Datentypen und Serialisierungs-Einstellungen, um sicherzustellen, dass Daten korrekt gespeichert werden.
Datenmodellierung und CRUD-Operationen mit MongoDB Atlas
Nun werden wir ein kurzes Beispiel zeigen, wie der MongoDB EF Core Provider verwendet werden kann. Momentan werden wir jedoch ein vollständiges Projekt in Visual Studio Code erstellen, sodass Sie alles in seiner Gesamtheit sehen können.
In diesem Abschnitt werden wir erkunden, wie man Datenmodelle definiert und CRUD-Operationen (Erstellen, Lesen, Aktualisieren, Löschen) mit dem MongoDB Entity Framework Core (EF) Provider mit MongoDB Atlas durchführt. Diese Integration ermöglicht es Ihnen, die Flexibilität von MongoDB mit den vertrauten Pattern von EF Core zu nutzen.
Erstellen Sie Ihre Umgebung
Um zu beginnen, müssen Sie die notwendigen NuGet-Pakete Ihrem Projekt hinzufügen:
dotnet add package MongoDB.EntityFrameworkCore
Das MS EF Core-Paket und der MongoDB C#-Treiber werden als Abhängigkeit hinzugefügt, wenn Sie das MongoDB EF Core-Anbieterpaket hinzufügen. Diese Pakete ermöglichen Ihrer Anwendung, mit MongoDB über EF Core zu interagieren, indem Sie die gleichen Kontexte und Entitätsdefinitionen verwenden, die Sie für eine relationale Datenbank verwenden würden.
Einrichten von MongoDB Atlas
Bevor Sie CRUD-Operationen durchführen können, müssen Sie einen MongoDB Atlas-Cluster einrichten und Ihre Anwendung dazu verbinden.
Hier sind die Schritte. Beachten Sie, dass wir diese detailliert in der nächsten Phase des Projektentwicklungsprozesses durchgehen werden.
-
Erstellen Sie ein MongoDB Atlas-Konto: Melden Sie sich bei MongoDB Atlas an.
-
Cluster erstellen: Ein neues Cluster aufsetzen. MongoDB Atlas bietet einen kostenfreien Tiered an, der perfekt für Entwicklung und kleine Skalierungsanwendungen ist.
-
Verbindungskennung erhalten: Holen Sie Ihre Verbindungskennung vom MongoDB Atlas-Dashboard. Sie sieht etwa so aus:
mongodb+srv://<username>:<password>@cluster0.mongodb.net/myFirstDatabase?retryWrites=true&w=majority
Datenmodell definieren
Definiert eine Klasse, die als Modell für Ihre Entität verwendet wird. In diesem Beispiel erstellen wir eine Customer
Klasse:
public class Customer
{
public ObjectId Id { get; set; }
public String Name { get; set; }
public String Order { get; set; }
}
Diese Customer
Klasse repräsentiert die Struktur der Dokumente, die in der MongoDB-Sammlung gespeichert sind.
DB Kontextklasse erstellen
Um Entity Framework Core zu verwenden, erstellen Sie eine Kontextklasse, die von DBContext abgeleitet ist. DieDbContext
abgeleitete Klasseinstanz repräsentiert eine Datenbank-Sitzung und wird verwendet, um nach Instanzen Ihrer Entitäten zu suchen und zu speichern.
Die DbContext
Klasse zeigt DBSet
Eigenschaften an, die die Entitäten angeben, mit denen Sie sich während der Verwendung dieses Kontextes interagieren können.
Dieses Beispiel erstellt eine Instanz einer von DBContext
abgeleiteten Klasse und legt das Customer
-Objekt als DBSet
-Eigenschaft fest:
public class MyDbContext : DbContext
{
public DbSet<Customer> Customers { get; init; }
public MyDbContext(DbContextOptions options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Customer>().ToCollection("customers");
}
}
Code-First-Workflow
Mit dem MongoDB EF Provider kann ein code-first-Workflow verwendet werden. Dies bedeutet, dass Sie zuerst Ihre Klassen definieren, und EF Core die Erstellung und Verwaltung der unterliegenden MongoDB-Schema übernehmen wird. Dies ist insbesondere für MongoDB nützlich, da dieses kein Schema durchsetzt, was flexiblen und dynamischen Datenstrukturen zugutekommt.
MongoDB verwenden
Sobald wir eine DBContext
-Klasse erstellt haben, müssen wir ein DbContextOptionsBuilder
-Objekt konstruieren und dessen UseMongoDB()
-Methode aufrufen. Diese Methode nimmt zwei Parameter entgegen: einen MongoClient
-Instanz und den Namen der Datenbank, die die Sammlungen aufbewahrt, mit denen Sie arbeiten.
Die Methode UseMongoDB()
gibt ein DbContextOptions
-Objekt zurück. Geben Sie die Eigenschaft Options
the dieses Objekts dem Konstruktor Ihrer DBContext
-Klasse zu.
var mongoClient = new MongoClient("<Your MongoDB Connection URI>");
var dbContextOptions =
new DbContextOptionsBuilder<MyDbContext>().UseMongoDB(mongoClient, "<Database Name");
var db = new MyDbContext(dbContextOptions.Options);
CRUD-Operationen
Nun sehen wir, wie wir die CRUD-Operationen coden. Wir konzentrieren uns einfach auf jede Operation separat.
Schreiben Operation
Um einen neuen Datensatz in MongoDB anzulegen, verwenden Sie die Add
-Methode auf der DbSet
und rufen SaveChanges
auf. Hier ist ein Beispiel zur Erstellung eines neuen Kunden:
using (var context = new MyDbContext(options))
{
var customer = new Customer { Name = "Beau Carnes", Order = "Laptop" };
context.Customers.Add(customer);
context.SaveChanges();
}
Dieser Code erstellt eine neue Customer
-Instanz und fügt sie der Customers
-Sammlung hinzu. Die Methode SaveChanges
fügt den neuen Kunden in die MongoDB-Datenbank ein.
Lesen Operation
Um Dokumente aus der MongoDB-Sammlung zu lesen, kannst du LINQ-Abfragen auf der DbSet
verwenden. Dies ist ein Beispiel für die Abfrage aller Kunden:
using (var context = new MyDbContext(options))
{
var customers = context.Customers.ToList();
foreach (var customer in customers)
{
Console.WriteLine($"Customer: {customer.Name}, Order: {customer.Order}");
}
}
Dieser Code liest alle Kunden aus der Customers
-Sammlung aus und gibt ihre Details aus.
Aktualisierungsoperation
Um ein vorhandenes Dokument zu aktualisieren, retrieviert du das Dokument, ändert seine Eigenschaften und ruft SaveChanges
auf. Dies ist ein Beispiel für die Aktualisierung einer Bestellung eines Kunden:
using (var context = new MyDbContext(options))
{
var customer = context.Customers.FirstOrDefault(c => c.Name == "Beau Carnes");
if (customer != null)
{
customer.Order = "Smartphone";
context.SaveChanges();
}
}
Dieser Code sucht den Kunden mit dem Namen „Beau Carnes“ und aktualisiert ihre Bestellung auf „Smartphone“.
Löschoperation
Um ein Dokument zu löschen, retrieviert du das Dokument, entfernst es aus der DbSet
und ruft SaveChanges
auf. Dies ist ein Beispiel für das Löschen eines Kunden:
using (var context = new MyDbContext(options))
{
var customer = context.Customers.FirstOrDefault(c => c.Name == "Beau Carnes");
if (customer != null)
{
context.Customers.Remove(customer);
context.SaveChanges();
}
}
Dieser Code sucht den Kunden mit dem Namen „Beau Carnes“ und löscht ihn aus der Customers
-Sammlung.
Verfolgung von Änderungen
Die Änderungsverfolgungsmöglichkeiten von EF Core werden vollständig unterstützt, was effiziente Aktualisierungen von Dokumenten ermöglicht. Wenn du eine Entität veränderst und SaveChanges
aufrufst, generiert EF Core die notwendigen MongoDB-Befehle, um nur die veränderten Felder zu aktualisieren.
Durch die Verwendung des MongoDB EF-Providers kannst du die flexible Dokumentenmodelle von MongoDB mit den robusten ORM-Fähigkeiten von EF Core problemlos integrieren, was .NET-Entwicklern ein mächtiges Werkzeug bereitstellt, um moderne Anwendungen zu entwickeln.
Tutorial
Nun lass uns alles zusammenfassen und ein Restaurant reservierungssystem erstellen.
Voraussetzungen
Um diesem Tutorial zu folgen, brauchen Sie einige Dinge:
-
.NET 7.0.
-
Grundkenntnisse von ASP.NET MVC und C#.
Erstellen Sie das Projekt
ASP.NET Core ist ein sehr flexibles Web-Framework, das Ihnen ermöglicht, verschiedene Arten von Webanwendungen zu erstellen, die geringfügige Unterschiede in Bezug auf UI oder Struktur aufweisen. Für dieses Tutorial werden wir ein MVC-Projekt erstellen, das statische Dateien und Controller verwendet. Es gibt andere Arten von Front-End, die Sie verwenden könnten, z. B. React, aber MVC mit .cshtml-Ansichten ist am häufigsten verwendet. Um das Projekt zu erstellen, verwenden wir die .NET CLI:
dotnet new mvc -o RestRes
Da wir die CLI verwendet haben, erstellt diese zwar einfach nur die csproj-Datei, aber keine Lösungsdatei, die es ermöglicht, das Projekt in Visual Studio zu öffnen, also werden wir das korrigieren.
cd RestRes
dotnet new sln
dotnet sln .\RestRes.sln add .\RestRes.csproj
Fügen Sie die NuGet-Pakete hinzu
Nun, da wir das neue Projekt erstellt haben, werden wir die erforderlichen NuGet-Pakete hinzufügen. Entweder mit dem NuGet-Paket-Manager oder mit dem untenstehenden Befehl der .NET CLI fügen Sie das MongoDB MongoDB.EntityFrameworkCore-Paket hinzu.
dotnet add package MongoDB.EntityFrameworkCore
Erstellen Sie die Modelle
Bevor wir die neu hinzugefügten Pakete implementieren können, müssen wir die Modelle erzeugen, die die Entitäten repräsentieren, die wir im Restaurantreservierungssystem haben möchten. Diese werden natürlich als Dokumente in MongoDB Atlas gespeichert. In den folgenden Unter Abschnitten werden wir die folgenden Modelle erzeugen:
-
Restaurant
-
Reservation
-
MongoDBSettings
Zuerst müssen wir ein Restaurant-Modell erzeugen, das die Restaurants repräsentiert, die im System reserviert werden können.
Erstellen Sie ein neues Datei im Ordner Models mit dem Namen Restaurant.cs.
-
Create a new file in the Models folder called Restaurant.cs.
-
Add the following code:
using MongoDB.Bson;
using MongoDB.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
namespace RestRes.Models
{
[Collection("restaurants")]
public class Restaurant
{
public ObjectId Id { get; set; }
[Required(ErrorMessage = "You must provide a name")]
[Display(Name = "Name")]
public string? name { get; set; }
[Required(ErrorMessage = "You must add a cuisine type")]
[Display(Name = "Cuisine")]
public string? cuisine { get; set; }
[Required(ErrorMessage = "You must add the borough of the restaurant")]
public string? borough { get; set; }
}
}
Das Attribut collection vor der Klasse informiert die Anwendung, welche Sammlung innerhalb der Datenbank wir verwenden. Dies ermöglicht es uns unterschiedliche Namen oder Groß-/Kleinschreibung zwischen unserer Klasse und unserer Sammlung zu haben, sollten wir das wollen.
Wir müssen auch eine Reservierungs-Klasse erstellen, um jede Reservation, die wir im System aufnehmen, zu repräsentieren.
Erstellen Sie eine neue Datei im Ordner Models mit dem Namen Reservation.cs.
-
Create a new file inside the Models folder called Reservation.cs.
-
Add the following code to it:
using MongoDB.Bson;
using MongoDB.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
namespace RestRes.Models
{
[Collection("reservations")]
public class Reservation
{
public ObjectId Id { get; set; }
public ObjectId RestaurantId { get; set; }
public string? RestaurantName { get; set; }
[Required(ErrorMessage = "The date and time is required to make this reservation")]
[Display(Name = "Date")]
public DateTime date { get; set; }
}
}
MongoDBSettings
Obwohl es kein Dokument in unserer Datenbank sein wird, benötigen wir eine Modelklassen, um unsere MongoDB-bezogenen Einstellungen zu speichern, damit sie über die gesamte Anwendung genutzt werden können.
-
Erstellen Sie eine weitere Datei in Models mit dem Namen MongoDBSettings.cs.
-
Fügen Sie folgenden Code hinzu:
namespace RestRes.Models
{
public class MongoDBSettings
{
public string AtlasURI { get; set; }
public string DatabaseName { get; set; }
}
}
Einrichten von EF Core
Das ist der spannende Teil. Wir werden mit der Implementierung von EF Core beginnen und den neuen MongoDB Provider nutzen. Wenn Sie bereits mit EF Core gearbeitet haben, wird Ihnen einiges bekannt vorkommen.
RestaurantReservationDbContext
-
Erstellen Sie einen Ordner namens Services und legen Sie eine Datei mit dem Namen RestaurantReservationDbContext.cs an.
-
Ersetzen Sie den Code innerhalb des Namespaces durch folgenden:
using Microsoft.EntityFrameworkCore;
using RestRes.Models;
namespace RestRes.Services
{
public class RestaurantReservationDbContext : DbContext
{
public DbSet<Restaurant> Restaurants { get; init; }
public DbSet<Reservation> Reservations { get; init; }
public RestaurantReservationDbContext(DbContextOptions options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Restaurant>();
modelBuilder.Entity<Reservation>();
}
}
}
Wenn Sie sich an EF Core gewöhnt haben, dürfte dies Ihnen bekannt vorkommen. Die Klasse erbt von DbContext und wir erstellen DbSet-Properties, die die Modelle enthalten, die auch in der Datenbank vorhanden sein werden. Wir überschreiben außerdem die OnModelCreating-Methode. Sie mögen bemerken, dass wir, anders als bei der Verwendung von SQL Server, nicht .ToTable() aufrufen. Wir könnten stattdessen ToCollection aufrufen, aber dies ist hier nicht notwendig, da wir die Sammlung mithilfe von Attributen auf den Klassen angeben.
Fügen Sie Verbindungszeichenfolge und Datenbankdetails zu appsettings hinzu.
Früher haben wir ein MongoDBSettings-Model erstellt, und nun müssen wir die Werte, die die Eigenschaften zugeordnet sind, in unsere appsettings.
-
In beiden appsettings.json und appsettings.Development.json fügen Sie die folgende neue Abschnitt hinzu:
"MongoDBSettings": { "AtlasURI": "mongodb+srv://<username>:<password>@<url>", "DatabaseName": "restaurants" }
-
Ersetzen Sie die Atlas-URI mit Ihrer eigenen Verbindungsinformation von Atlas.
Update des program.cs
Nun haben wir unsere Modelle und DbContext konfiguriert, es ist Zeit, sie zum Datei program.cs hinzuzufügen.
Nach der vorhandenen Zeile builder.Services
.AddControllersWithViews();
, fügen Sie folgenden Code hinzu:
var mongoDBSettings = builder.Configuration.GetSection("MongoDBSettings").Get<MongoDBSettings>();
builder.Services.Configure<MongoDBSettings>(builder.Configuration.GetSection("MongoDBSettings"));
builder.Services.AddDbContext<RestaurantReservationDbContext>(options =>
options.UseMongoDB(mongoDBSettings.AtlasURI ?? "", mongoDBSettings.DatabaseName ?? ""));
Erstellen Sie die Dienste.
Jetzt ist es Zeit, die Dienste hinzuzufügen, die wir verwenden, um mit der Datenbank über das RestaurantBookingDbContext zu sprechen, den wir erstellt haben. Für jeden Dienst erstellen wir eine Schnittstelle und die Klasse, die sie implementiert.
IRestaurantService und RestaurantService
Der erste Interface und der Dienst, den wir implementieren, ist dafür da, die CRUD-Operationen auf der Sammlung der Restaurants durchzuführen. Dies wird als Repository-Muster bezeichnet. Manchmal sehen Sie Menschen direkt mit dem DbContext interagieren. Die meisten Leute verwenden jedoch dieses Muster, weshalb wir es hier einfügen.
-
Wenn Sie es noch nicht getan haben, erstellen Sie einen Services-Ordner, um unsere neuen Klassen aufzubewahren.
-
Erstellen Sie ein IRestaurantService-Interface und fügen Sie den folgenden Code für die Methoden hinzu, die wir implementieren werden:
using MongoDB.Bson;
using RestRes.Models;
namespace RestRes.Services
{
public interface IRestaurantService
{
IEnumerable<Restaurant> GetAllRestaurants();
Restaurant? GetRestaurantById(ObjectId id);
void AddRestaurant(Restaurant newRestaurant);
void EditRestaurant(Restaurant updatedRestaurant);
void DeleteRestaurant(Restaurant restaurantToDelete);
}
}
-
Erstellen Sie eine RestaurantService-Klassendatei.
-
Aktualisieren Sie die Deklaration der RestaurantService-Klasse, sodass sie das gerade erstellte IRestaurantService implementiert:
using Microsoft.EntityFrameworkCore;
using MongoDB.Bson;
using MongoDB.Driver;
using RestRes.Models;
namespace RestRes.Services
{
public class RestaurantService : IRestaurantService
{
private readonly RestaurantReservationDbContext _restaurantDbContext;
public RestaurantService(RestaurantReservationDbContext restaurantDbContext)
{
_restaurantDbContext = restaurantDbContext;
}
public void AddRestaurant(Restaurant restaurant)
{
_restaurantDbContext.Restaurants.Add(restaurant);
_restaurantDbContext.ChangeTracker.DetectChanges();
Console.WriteLine(_restaurantDbContext.ChangeTracker.DebugView.LongView);
_restaurantDbContext.SaveChanges();
}
public void DeleteRestaurant(Restaurant restaurant)
{
var restaurantToDelete = _restaurantDbContext.Restaurants.Where(c => c.Id == restaurant.Id).FirstOrDefault();
if(restaurantToDelete != null) {
_restaurantDbContext.Restaurants.Remove(restaurantToDelete);
_restaurantDbContext.ChangeTracker.DetectChanges();
Console.WriteLine(_restaurantDbContext.ChangeTracker.DebugView.LongView);
_restaurantDbContext.SaveChanges();
}
else {
throw new ArgumentException("The restaurant to delete cannot be found.");
}
}
public void EditRestaurant(Restaurant restaurant)
{
var restaurantToUpdate = _restaurantDbContext.Restaurants.FirstOrDefault(c => c.Id == restaurant.Id);
if(restaurantToUpdate != null)
{
restaurantToUpdate.name = restaurant.name;
restaurantToUpdate.cuisine = restaurant.cuisine;
restaurantToUpdate.borough = restaurant.borough;
_restaurantDbContext.Restaurants.Update(restaurantToUpdate);
_restaurantDbContext.ChangeTracker.DetectChanges();
Console.WriteLine(_restaurantDbContext.ChangeTracker.DebugView.LongView);
_restaurantDbContext.SaveChanges();
}
else
{
throw new ArgumentException("The restaurant to update cannot be found. ");
}
}
public IEnumerable<Restaurant> GetAllRestaurants()
{
return _restaurantDbContext.Restaurants.OrderByDescending(c => c.Id).Take(20).AsNoTracking().AsEnumerable<Restaurant>();
}
public Restaurant? GetRestaurantById(ObjectId id)
{
return _restaurantDbContext.Restaurants.FirstOrDefault(c => c.Id == id);
}
}
}
IReservationService und ReservationService
Der nächste Schritt ist unser IReservationService und ReservationService.
Erstellen Sie das IReservationService-Interface und fügen Sie die folgenden Methoden hinzu:
using MongoDB.Bson;
using RestRes.Models;
namespace RestRes.Services
{
public interface IReservationService
{
IEnumerable<Reservation> GetAllReservations();
Reservation? GetReservationById(ObjectId id);
void AddReservation(Reservation newReservation);
void EditReservation(Reservation updatedReservation);
void DeleteReservation(Reservation reservationToDelete);
}
}
Erstellen Sie die Klasse ReservationService und ersetzen Sie Ihre Klasse mit dem folgenden Code, der alle Methoden implementiert:
using Microsoft.EntityFrameworkCore;
using MongoDB.Bson;
using RestRes.Models;
namespace RestRes.Services
{
public class ReservationService : IReservationService
{
private readonly RestaurantReservationDbContext _restaurantDbContext;
public ReservationService(RestaurantReservationDbContext restaurantDbContext)
{
_restaurantDbContext = restaurantDbContext;
}
public void AddReservation(Reservation newReservation)
{
var bookedRestaurant = _restaurantDbContext.Restaurants.FirstOrDefault(c => c.Id == newReservation.RestaurantId);
if (bookedRestaurant == null)
{
throw new ArgumentException("The restaurant to be reserved cannot be found.");
}
newReservation.RestaurantName = bookedRestaurant.name;
_restaurantDbContext.Reservations.Add(newReservation);
_restaurantDbContext.ChangeTracker.DetectChanges();
Console.WriteLine(_restaurantDbContext.ChangeTracker.DebugView.LongView);
_restaurantDbContext.SaveChanges();
}
public void DeleteReservation(Reservation reservation)
{
var reservationToDelete = _restaurantDbContext.Reservations.FirstOrDefault(b => b.Id == reservation.Id);
if(reservationToDelete != null)
{
_restaurantDbContext.Reservations.Remove(reservationToDelete);
_restaurantDbContext.ChangeTracker.DetectChanges();
Console.WriteLine(_restaurantDbContext.ChangeTracker.DebugView.LongView);
_restaurantDbContext.SaveChanges();
}
else
{
throw new ArgumentException("The reservation to delete cannot be found.");
}
}
public void EditReservation(Reservation updatedReservation)
{
var reservationToUpdate = _restaurantDbContext.Reservations.FirstOrDefault(b => b.Id == updatedReservation.Id);
if (reservationToUpdate != null)
{
reservationToUpdate.date = updatedReservation.date;
_restaurantDbContext.Reservations.Update(reservationToUpdate);
_restaurantDbContext.ChangeTracker.DetectChanges();
_restaurantDbContext.SaveChanges();
Console.WriteLine(_restaurantDbContext.ChangeTracker.DebugView.LongView);
}
else
{
throw new ArgumentException("Reservation to be updated cannot be found");
}
}
public IEnumerable<Reservation> GetAllReservations()
{
return _restaurantDbContext.Reservations.OrderBy(b => b.date).Take(20).AsNoTracking().AsEnumerable<Reservation>();
}
public Reservation? GetReservationById(ObjectId id)
{
return _restaurantDbContext.Reservations.AsNoTracking().FirstOrDefault(b => b.Id == id);
}
}
}
Der Code ist sehr ähnlich dem Code für die Klasse RestaurantService, aber er ist für Reservierungen gedacht.
Das Hinzufügen von Abhängigkeitsinjektion
Der letzte Schritt für die Dienste besteht darin, sie zum Abhängigkeitsinjektionscontainer hinzuzufügen.
Innerhalb von Program.cs fügen Sie dem Code, den wir dort zuvor hinzugefügt haben, folgenden Code hinzu:
builder.Services.AddScoped<IRestaurantService, RestaurantService>();
builder.Services.AddScoped<IReservationService, ReservationService>();
Erstellen Sie die View Models
Vor dem Implementieren des Front-Ends müssen wir die View Models hinzufügen, die als Boten zwischen unserem Front-End und Back-End fungieren, wo erforderlich. Auch wenn unsere Anwendung recht einfach ist, ist das Implementieren von View Models immer noch eine gute Praxis, da es das Dekouplen der Teile der Anwendung unterstützt.
RestaurantListViewModel
Der erste, den wir hinzufügen, ist der RestaurantListViewModel. Dieser wird später als Modell in unserer Razor-Seite verwendet, um Restaurants aus der Datenbank aufzulisten.
-
Erstellen Sie im Stammordner des Projekts einen neuen Ordner namens ViewModels.
-
Fügen Sie eine neue Datei mit dem Namen RestaurantListViewModel.cs hinzu.
-
Fügen Sie folgenden Code hinzu:
using RestRes.Models;
namespace RestRes.ViewModels
{
public class RestaurantListViewModel
{
public IEnumerable<Restaurant>? Restaurants { get; set; }
}
}
RestaurantAddViewModel
Wir möchten auch ein View Model, das später für die hinzuzufügende Ansicht verwendet werden kann.
-
Innerhalb des Ordners ViewModels erstellen Sie eine neue Datei mit dem Namen RestaurantAddViewModel.cs.
-
Hinzufügen:
using RestRes.Models;
namespace RestRes.ViewModels
{
public class RestaurantAddViewModel
{
public Restaurant? Restaurant { get; set; }
}
}
ReservationListViewModel
nun möchten wir für Reservierungen etwas Ähnliches tun, beginnend mit ReservationListViewModel.
-
Erstellen Sie eine neue Datei im Ordner ViewModels mit dem Namen ReservationListViewModel.cs.
-
Hinzufügen:
using RestRes.Models;
namespace RestRes.ViewModels
{
public class ReservationListViewModel
{
public IEnumerable<Reservation>? Reservations { get; set; }
}
}
ReservationAddViewModel
Schließlich haben wir unser ReservationAddViewModel.
Erstellen Sie die Datei und fügen Sie diesen Code hinzu:
using RestRes.Models;
namespace RestRes.ViewModels
{
public class ReservationAddViewModel
{
public Reservation? Reservation { get; set; }
}
}
Hinzufügen zu _ViewImports
Später werden wir in den Ansichten Verweise auf unsere Modelle und ViewModelle hinzufügen. Damit die Anwendung weiß, was es mit ihnen auf sich hat, müssen wir ihnen in der Datei _ViewImports.cshtml im Ordner Views Verweise hinzufügen.
Es gibt dort bereits einige Verweise, einschließlich TagHelpers, also möchten wir Verweise auf unsere .Models- und .ViewModels-Ordner hinzufügen. Daher sollte der Anfang der Datei so aussehen:
@using RestRes
@using RestRes.Models
@using RestRes.ViewModels
Erstellen der Controller
Nun, da wir die Backend-Implementierung und die ViewModelle, die wir referenzieren, haben, können wir anfangen, uns auf die Frontendseite zu konzentrieren. Wir werden zwei Controller erzeugen: einen für Restaurant und einen für Reservierung.
RestaurantController
Der erste Controller, den wir hinzufügen, ist für das Restaurant.
-
Im bestehenden Controllers-Ordner fügen Sie ein neues Controller-Datei namens RestaurantController.cs hinzu. Wenn Sie Visual Studio verwenden, nutzen Sie den leeren MVC-Controller-Vorlagentemplate.
-
Fügen Sie diesen Code hinzu:
using Microsoft.AspNetCore.Mvc;
using MongoDB.Bson;
using RestRes.Models;
using RestRes.Services;
using RestRes.ViewModels;
namespace RestRes.Controllers
{
public class RestaurantController : Controller
{
private readonly IRestaurantService _RestaurantService;
public RestaurantController(IRestaurantService RestaurantService)
{
_RestaurantService = RestaurantService;
}
public IActionResult Index()
{
RestaurantListViewModel viewModel = new()
{
Restaurants = _RestaurantService.GetAllRestaurants(),
};
return View(viewModel);
}
public IActionResult Add()
{
return View();
}
[HttpPost]
public IActionResult Add(RestaurantAddViewModel restaurantAddViewModel)
{
if(ModelState.IsValid)
{
Restaurant newRestaurant = new()
{
name = restaurantAddViewModel.Restaurant.name,
borough = restaurantAddViewModel.Restaurant.borough,
cuisine = restaurantAddViewModel.Restaurant.cuisine
};
_RestaurantService.AddRestaurant(newRestaurant);
return RedirectToAction("Index");
}
return View(restaurantAddViewModel);
}
public IActionResult Edit(ObjectId id)
{
if(id == null || id == ObjectId.Empty)
{
return NotFound();
}
var selectedRestaurant = _RestaurantService.GetRestaurantById(id);
return View(selectedRestaurant);
}
[HttpPost]
public IActionResult Edit(Restaurant restaurant)
{
try
{
if(ModelState.IsValid)
{
_RestaurantService.EditRestaurant(restaurant);
return RedirectToAction("Index");
}
else
{
return BadRequest();
}
}
catch (Exception ex)
{
ModelState.AddModelError("", $"Updating the restaurant failed, please try again! Error: {ex.Message}");
}
return View(restaurant);
}
public IActionResult Delete(ObjectId id) {
if (id == null || id == ObjectId.Empty)
{
return NotFound();
}
var selectedRestaurant = _RestaurantService.GetRestaurantById(id);
return View(selectedRestaurant);
}
[HttpPost]
public IActionResult Delete(Restaurant restaurant)
{
if (restaurant.Id == ObjectId.Empty)
{
ViewData["ErrorMessage"] = "Deleting the restaurant failed, invalid ID!";
return View();
}
try
{
_RestaurantService.DeleteRestaurant(restaurant);
TempData["RestaurantDeleted"] = "Restaurant deleted successfully!";
return RedirectToAction("Index");
}
catch (Exception ex)
{
ViewData["ErrorMessage"] = $"Deleting the restaurant failed, please try again! Error: {ex.Message}";
}
var selectedRestaurant = _RestaurantService.GetRestaurantById(restaurant.Id);
return View(selectedRestaurant);
}
}
}
ReservationController
Nun den Reservierungs-Controller. Dieser ist sehr ähnlich dem RestaurantController, besitzt jedoch eine Referenz auf sowohl das Restaurant als auch die Reservierungs-Service, da wir ein Restaurant mit einer Reservierung assoziieren müssen. Dies, weil der momentan EF Core Provider keine Beziehungen zwischen Entitäten unterstützt, sodass wir Entitäten auf eine andere Weise assoziieren können.
-
Erstellen Sie eine weitere leere MVC-Controller-Datei namens ReservationController.cs.
-
Fügen Sie folgender Code hinzu:
using Microsoft.AspNetCore.Mvc;
using MongoDB.Bson;
using RestRes.Models;
using RestRes.Services;
using RestRes.ViewModels;
namespace RestRes.Controllers
{
public class ReservationController : Controller
{
private readonly IReservationService _ReservationService;
private readonly IRestaurantService _RestaurantService;
public ReservationController(IReservationService ReservationService, IRestaurantService RestaurantService)
{
_ReservationService = ReservationService;
_RestaurantService = RestaurantService;
}
public IActionResult Index()
{
ReservationListViewModel viewModel = new ReservationListViewModel()
{
Reservations = _ReservationService.GetAllReservations()
};
return View(viewModel);
}
public IActionResult Add(ObjectId restaurantId)
{
var selectedRestaurant = _RestaurantService.GetRestaurantById(restaurantId);
ReservationAddViewModel reservationAddViewModel = new ReservationAddViewModel();
reservationAddViewModel.Reservation = new Reservation();
reservationAddViewModel.Reservation.RestaurantId = selectedRestaurant.Id;
reservationAddViewModel.Reservation.RestaurantName = selectedRestaurant.name;
reservationAddViewModel.Reservation.date = DateTime.UtcNow;
return View(reservationAddViewModel);
}
[HttpPost]
public IActionResult Add(ReservationAddViewModel reservationAddViewModel)
{
Reservation newReservation = new()
{
RestaurantId = reservationAddViewModel.Reservation.RestaurantId,
date = reservationAddViewModel.Reservation.date,
};
_ReservationService.AddReservation(newReservation);
return RedirectToAction("Index");
}
public IActionResult Edit(string Id)
{
if(Id == null || string.IsNullOrEmpty(Id))
{
return NotFound();
}
var selectedReservation = _ReservationService.GetReservationById(new ObjectId(Id));
return View(selectedReservation);
}
[HttpPost]
public IActionResult Edit(Reservation reservation)
{
try
{
var existingReservation = _ReservationService.GetReservationById(reservation.Id);
if (existingReservation != null)
{
_ReservationService.EditReservation(reservation);
return RedirectToAction("Index");
}
else
{
ModelState.AddModelError("", $"Reservation with ID {reservation.Id} does not exist!");
}
}
catch (Exception ex)
{
ModelState.AddModelError("", $"Updating the reservation failed, please try again! Error: {ex.Message}");
}
return View(reservation);
}
public IActionResult Delete(string Id)
{
if (Id == null || string.IsNullOrEmpty(Id))
{
return NotFound();
}
var selectedReservation = _ReservationService.GetReservationById(new ObjectId(Id));
return View(selectedReservation);
}
[HttpPost]
public IActionResult Delete(Reservation reservation)
{
if(reservation.Id == null)
{
ViewData["ErrorMessage"] = "Deleting the reservation failed, invalid ID!";
return View();
}
try
{
_ReservationService.DeleteReservation(reservation);
TempData["ReservationDeleted"] = "Reservation deleted successfully";
return RedirectToAction("Index");
}
catch (Exception ex)
{
ViewData["ErrorMessage"] = $"Deleting the reservation failed, please try again! Error: {ex.Message}";
}
var selectedRestaurant = _ReservationService.GetReservationById(reservation.Id);
return View(selectedRestaurant);
}
}
}
Erstellung der Ansichten
Nun haben wir das Backend und die Controller mit den Endpunkten für unser Restaurantreservierungssystem vorbereitet, es ist Zeit, die Ansichten zu implementieren. Dies wird mit Razor-Seiten erfolgen. Sie werden auch auf Hinweise auf Klassen aus Bootstrap stoßen, da dies die mit MVC-Anwendungen ausgeliefert wird. Wir werden für die CRUD-Operationen sowohl für Listen als auch Buchungen Ansichten bereitstellen.
Liste der Restaurants
Zuerst werden wir eine Ansicht bereitstellen, die auf die Wurzel von /Restaurant verweist, die standardmäßig die Index-Methode aufruft, die wir implementiert haben.
ASP.NET Core MVC verwendet ein Konventionenmuster, bei dem die Datei mit dem Dateinamen des Endpunkts/Methodennamens bezeichnet wird und sie in einem Ordner mit dem Namen ihres Controllers liegt.
-
Legen Sie im Ordner Views ein neues Unterordner namens Restaurant an.
-
In diesem Restaurant-Ordner erstellen Sie eine neue Ansicht, indem Sie eine Datei namens
Index.cshtml
anlegen. Wenn Sie die verfügbaren Vorlagen verwenden, sollten Sie Razor View – Leer auswählen. Nennen Sie die Ansicht Index. -
Fügen Sie diesen Code hinzu:
@model RestaurantListViewModel
@if (TempData["RestaurantDeleted"] != null)
{
<p class="text-success">@TempData["RestaurantDeleted"]</p>
}
@if (!Model.Restaurants.Any())
{
<p>No results</p>
}
else
{
<table class="table table-condensed table-bordered">
<tr>
<th>
Name
</th>
<th>
Cuisine
</th>
<th>
Borough
</th>
<th>
Actions
</th>
</tr>
@foreach (var restaurant in Model.Restaurants)
{
<tr>
<td>@restaurant.name</td>
<td>@restaurant.cuisine</td>
<td>@restaurant.borough</td>
<td>
<a asp-action="Edit" asp-route-id="@restaurant.Id.ToString()">Edit</a>
<a asp-action="Delete" asp-route-id="@restaurant.Id.ToString()">Delete</a>
<a asp-controller="Reservation" asp-action="Add" asp-route-restaurantId="@restaurant.Id.ToString()">Reserve</a>
</td>
</tr>
}
</table>
}
<p>
<a class="btn btn-primary" asp-action="Add">Add new restaurant</a>
</p>
Nun bearbeiten wir die Standardroute von Home auf /Restaurant.
In Program.cs, innerhalb von app.MapControllerRoute
, ersetzen Sie die Zeile mit dem Muster folgendermaßen:
pattern: "{controller=Restaurant}/{action=Index}/{id?}");
Wenn wir dies jetzt ausführen würden, würden die Schaltflächen zu 404s führen, weil wir sie noch nicht implementiert haben. So lassen Sie uns das jetzt tun.
Neue Restaurants hinzufügen
Wir beginnen mit dem Formular zur Hinzufügung neuer Restaurants.
-
Legen Sie im Restaurant-Unterordner eine neue, leere Razor-Ansicht mit dem Namen Add.cshtml an.
-
Füge den folgenden Code hinzu:
@model RestaurantAddViewModel
<h2>Create a new restaurant</h2>
<hr />
@if (ViewData["ErrorMessage"] != null)
{
<p class="text-danger">@ViewData["ErrorMessage"]</p>
}
<form method="post" asp-controller="Restaurant" asp-action="Add">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="mb-3">
<label asp-for="Restaurant.name" class="form-label"></label>
<input asp-for="Restaurant.name" class="form-control" />
<span asp-validation-for="Restaurant.name" class="text-danger"></span>
</div>
<div class="mb-3">
<label asp-for="Restaurant.cuisine" class="form-label"></label>
<input asp-for="Restaurant.cuisine" class="form-control" />
<span asp-validation-for="Restaurant.cuisine" class="text-danger"></span>
</div>
<div class="mb-3">
<label asp-for="Restaurant.borough" class="form-label">Borough</label>
<input asp-for="Restaurant.borough" class="form-control" />
<span asp-validation-for="Restaurant.borough" class="text-danger"></span>
</div>
<input type="submit" value="Add restaurant" class="btn btn-primary" />
</form>
<div>
<a asp-controller="Restaurant" asp-action="Index">Back to list</a>
</div>
Restaurants bearbeiten
Der Code für die Bearbeitungsseite ist fast identisch mit dem für das Hinzufügen, verwendet jedoch das Restaurant als Modell, da er das Restaurant, das ihm übergeben wird, zum Vorbefüllen des Formulars für die Bearbeitung verwenden wird.
-
Füge eine weitere Ansicht im Restaurantordner mit dem Namen Edit.cshtml hinzu.
-
Füge den folgenden Code hinzu:
@model Restaurant
<h2>Update @Model.name</h2>
<hr />
<form method="post" asp-controller="Restaurant" asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id" />
<div class="mb-3">
<label asp-for="name" class="form-label">Name</label>
<input asp-for="name" class="form-control" />
<span asp-validation-for="name" class="text-danger"/>
</div>
<div class="mb-3">
<label asp-for="cuisine" class="form-label"></label>
<input asp-for="cuisine" class="form-control" />
<span asp-validation-for="cuisine" class="text-danger"/>
</div>
<div class="mb-3">
<label asp-for="borough" class="form-label">Borough</label>
<input asp-for="borough" class="form-control" />
<span asp-validation-for="borough" class="text-danger"/>
</div>
<input type="submit" value="Update restaurant" class="btn btn-primary" />
</form>
<div>
<a asp-controller="Restaurant" asp-action="Index">Back to list</a>
</div>
Restaurants löschen
Die letzte Seite, die wir implementieren müssen, ist die Seite, die aufgerufen wird, wenn der Löschbutton geklickt wird.
-
Erstelle eine neue leere Ansicht mit dem Namen Delete.cshtml.
-
Füge den folgenden Code hinzu:
@model Restaurant
<h2>Deleting @Model.name</h2>
<hr />
@if(ViewData["ErrorMessage"] != null)
{
<p class="text-danger">@ViewData["ErrorMessage"]</p>
}
<div>
<dl class="row">
<dt class="col-sm-4">
<label asp-for="name">Name</label>
</dt>
<dd class="col-sm-10">
@Model?.name
</dd>
<dt class="col-sm-2">
<label asp-for="cuisine"></label>
</dt>
<dd class="col-sm-10">
@Model?.cuisine
</dd>
<dt class="col-sm-2">
<label asp-for="borough">Borough</label>
</dt>
<dd class="col-sm-10">
@Model?.borough
</dd>
</dl>
</div>
<form method="post" asp-action="Delete">
<input type="hidden" asp-for="Id" />
<input type="submit" value="Delete restaurant" class="btn btn-danger" onclick="javascript: return confirm('Are you sure you want to delete this restaurant?');" />
</form>
<div>
<a asp-controller="Restaurant" asp-action="Index">Back to list</a>
</div>
Reservierungen auflisten
Wir haben die Ansichten für die Restaurants hinzugefügt, jetzt werden wir die Ansichten für Reservierungen hinzufügen, beginnend mit der Auflistung vorhandener Reservierungen.
-
Erstelle einen neuen Ordner innerhalb des Ansichtsordners mit dem Namen Reservation.
-
Erstelle eine neue leere Ansichtsdatei mit dem Namen Index.cshtml.
-
Füge den folgenden Code hinzu, um die Reservierungen anzuzeigen, falls vorhanden:
@model ReservationListViewModel
@if (TempData["ReservationDeleted"] != null)
{
<p class="text-success">@TempData["ReservationDeleted"]</p>
}
@if (!Model.Reservations.Any())
{
<p>No results</p>
}
else
{
<table class="table table-condensed table-bordered">
<tr>
<th>
Booked Restaurant
</th>
<th>
Date and Time
</th>
<th>
Actions
</th>
</tr>
@foreach(var reservation in Model.Reservations)
{
<tr>
<td>@reservation.RestaurantName</td>
<td>@reservation.date.ToLocalTime()</td>
<td>
<a asp-action="Edit" asp-route-id="@reservation.Id.ToString()">Edit</a>
<a asp-action="Delete" asp-route-id="@reservation.Id.ToString()">Delete</a>
</td>
</tr>
}
</table>
}
Reservierungen hinzufügen
Die Reservierungen hinzufügen ist nächstes.
-
Erstellen Sie eine leere Ansicht namens Add.cshtml.
-
Fügen Sie folgenden Code hinzu:
@model ReservationAddViewModel
@if (ViewData["ErrorMessage"] != null)
{
<p class="text-danger">@ViewData["ErrorMessage"]</p>
}
<form method="post" asp-controller="Reservation" asp-action="Add">
<div asp-validation-summary="All" class="text-danger"></div>
<input type="hidden" asp-for="Reservation.Id" />
<input type="hidden" asp-for="Reservation.RestaurantId" />
<div class="mb-3">
<label asp-for="Reservation.date" class="form-label"></label>
<input asp-for="Reservation.date" type="datetime-local" class="form-control" value="@DateTime.Now.ToString("yyyy-MM-ddTHH:mm")" />
<span asp-validation-for="Reservation.date" class="text-danger"></span>
</div>
<input type="submit" value="Reserve table" class="btn btn-primary" />
</form>
Bearbeiten von Reservierungen
Nächstes ist das Bearbeiten von Reservierungen.
-
Erstellen Sie eine leere Ansicht namens Edit.cshtml.
-
Fügen Sie folgenden Code hinzu:
@model Reservation
<h2>Editing reservation for @Model.RestaurantName on @Model.date.ToLocalTime()</h2>
<hr />
<form method="post" asp-controller="Reservation" asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id" />
<div class="mb-3">
<label asp-for="date" class="form-label"></label>
<input asp-for="date" value="@Model.date.ToLocalTime().ToString("yyyy-MM-ddTHH:mm")" class="form-control" />
<span asp-validation-for="date" class="text-danger" />
</div>
<input type="submit" value="Update reservation" class="btn btn-primary" />
</form>
<div>
<a asp-controller="Reservation" asp-action="Index">Back to reservations</a>
</div>
Löschen von Reservierungen
Nächstes ist das Löschen von Reservierungen.
-
Erstellen Sie eine leere Ansicht namens Delete.cshtml.
-
Fügen Sie folgenden Code hinzu:
@model Reservation
<h2>Delete reservation</h2>
<hr />
@if (ViewData["ErrorMessage"] != null)
{
<p class="text-danger">@ViewData["ErrorMessage"]</p>
}
<div>
<dl class="row">
<dt class="col-sm-2">
<label asp-for="RestaurantName">Name</label>
</dt>
<dd class="col-sm-10">
@Model?.RestaurantName
</dd>
<dt class="col-sm-2">
<label asp-for="date"></label>
</dt>
<dd class="col-sm-10">
@Model?.date.ToLocalTime()
</dd>
</dl>
</div>
<form method="post" asp-action="Delete">
<input type="hidden" asp-for="Id" />
<input type="hidden" asp-for="RestaurantId" />
<input type="submit" value="Delete reservation" class="btn btn-danger" onclick="javascript: return confirm('Are you sure you want to delete this reservation?');" />
</form>
<div>
<a asp-controller="Reservation" asp-action="Index">Back to list</a>
</div>
Aktualisieren des Navigationsbars
Das letzte, was wir hinzufügen sollen, ist das Aktualisieren des Navigationsbars der Anwendung, sodass wir leicht zwischen Restaurants und Reservierungen wechseln können.
Gehe zu dem Datei Views/Shared/_Layout.cshtml
. Finde den div
mit der Klasse navbar-collapse
. Entferne diesen gesamten Abschnitt und füge den folgenden Code hinzu:
<div class="collapse navbar-collapse justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Restaurant" asp-action="Index">Restaurants</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Reservation" asp-action="Index">Reservations</a>
</li>
</ul>
</div>
Testen unserer Anwendung
Wir haben nun eine funktionierende Anwendung, die den neuen MongoDB-Provider für EF Core verwendet. Jetzt ist es Zeit, alles zu testen und unsere Endpunkte zu besuchen, um sicherzustellen, dass es alles funktioniert.
Führe im Terminal den folgenden Befehl aus:
dotnet run
Versuche, Restaurants zu bearbeiten und Reservierungen hinzuzufügen. Danach kannst du zu der MongoDB Atlas-Datenbankseite navigieren und erkennen, dass deine Änderungen in der Datenbank widerspiegeln.
Erweiterte MongoDB-Operationen: Atlas-Suche und Vektor-Suche
Der EF Core-Provider basiert auf dem MongoDB C# Driver. Da wir bereits beim Erstellen des DbContexts auf den MongoClient zugreifen können, ermöglicht das das Ausführen erweiterter MongoDB-Operationen wie Atlas-Suche und Vektor-Suche. Diese Features verbessern die Fähigkeiten deiner Anwendung, indem Sie leistungsstarke Suchfunktionen einführen, während Sie immer noch den vertrauten EF Core-Framework nutzen können.
Atlas-Suche
Atlas-Suche ist ein vollständiges Textsuchengert von MongoDB Atlas. Es ermöglicht es, auf Ihre MongoDB-Daten komplizierte Suchabfragen auszuführen. Mit Atlas-Suche können Sie Features wie Autovervollständigung, facettiertes Suchen und sortierte Relevanz einführen.
Um Atlas-Suche mit dem EF Core-Provider zu verwenden, führen Sie die folgenden Schritte aus:
-
Legen Sie in MongoDB Atlas Indizes fest:
-
Gehe zu Ihrem MongoDB Atlas-Cluster.
-
Navigieren Sie zum „Suche“-Tab und legen Sie einen neuen Index auf Ihre Sammlung an. Definieren Sie die Felder, die Sie durchsuchbar machen wollen.
-
-
Definieren Sie durchsuchbare Felder in Ihren Modellen: Stellen Sie sicher, dass die Felder, die Sie durchsuchen möchten, ordnungsgemäß definiert sind. Hier ist ein Beispiel für die Definition eines Produktmodells.
public class Produkt { public ObjectId Id { get; set; } public string Name { get; set; } public string Beschreibung { get; set; } public decimal Preis { get; set; } public string Kategorie { get; set; } }
-
Ausführen von Suchabfragen: Verwenden Sie die Möglichkeiten des MongoDB .NET-Treibers, um Textsuchen durchzuführen. Da EF Core die MongoDB-spezifische Syntax für die Suche nicht direkt unterstützt, müssen Sie den Treiber in Verbindung mit EF Core verwenden. Hier ist ein Beispiel:
using MongoDB.Driver; using MongoDB.Driver.Linq; var client = new MongoClient("Ihre-mongodb-Verbindungszeichenfolge"); var database = client.GetDatabase("Ihr-Datenbankname"); var collection = database.GetCollection<Produkt>("Produkte"); var Suchergebnis = collection.Aggregate() .Match(Builders<Produkt>.Filter.Text("Suchbegriff")) .ToList();
Dieses Beispiel zeigt, wie man eine Textsuche in der Sammlung Products
durchführt. Der Text
-Filter hilft bei der Suche in allen in Ihrem Atlas Search-Index definierten indizierten Feldern.
Vektorsuche
Vektorsuche in MongoDB wird verwendet, um Dokumente auf der Basis von Vektorsimilitäten zu suchen, was insbesondere für Anwendungen mit maschinellen Lernmethoden, Empfehlungen und natürlicher Sprachverarbeitung nützlich ist. Vektorsuche ermöglicht es Ihnen, Dokumente mithilfe von Vektoren zu durchsuchen, die Text, Bilder oder andere hochdimensionalen Daten repräsentieren.
-
Vektoren erzeugen und speichern: Zunächst sollten Sie sicherstellen, dass Ihre Dokumente Vektoren enthalten. Sie müssen Ihre Daten vielleicht vorverarbeiten, um diese Vektoren mit Hilfe von maschinellen Lernmodellen zu generieren.
-
Vektoren im MongoDB Atlas indizieren: Erstellen Sie einen besonderen Index auf dem Vektorfeld in MongoDB Atlas, um effiziente Vektorsimilitätssuchen zu ermöglichen.
-
Durchführung von Vektorsuchen: Verwenden Sie den MongoDB .NET Treiber, um basierend auf Vektorähnlichkeit abzufragen.
Integration mit EF Core
Während der MongoDB EF Core Provider CRUD-Operationen vereinfacht, erfordern einige erweiterte Funktionen wie Atlas Search und Vector Search die direkte Verwendung des MongoDB .NET Treibers. Sie können diese Operationen jedoch immer noch in Ihrer auf EF Core basierenden Anwendung integrieren, indem Sie den Treiber für Suchfunktionen und EF Core für andere Datenverwaltungsaufgaben verwenden.
Durch die Kombination von EF Core und den erweiterten Funktionen von MongoDB können Sie leistungsstarke und flexible Anwendungen erstellen, die das Beste aus beiden Welten nutzen – strukturierte Datenzugriffsmuster von EF Core und die leistungsstarken Suchmöglichkeiten von MongoDB Atlas.
Source:
https://www.freecodecamp.org/news/using-entity-framework-core-with-mongodb/