Entity Framework Core is een populair ORM (Object-Relationele Mapper) voor .NET-toepassingen, die ontwikkelaars toestaat databases te werken met .NET-objecten. Het kan worden gebruikt met vele typen databases, inclusief MongoDB.

In dit artikel zult u leren hoe u Entity Framework Core kunt gebruiken met MongoDB. dit artikel biedt de basis, uitlegt de voordelen en biedt een stap-voor-stap handleiding. Of u nu nieuw bent bij MongoDB of Entity Framework Core, of alleen maar op zoek bent om deze tools te integreren in uw .NET-projecten, helpt dit gids u de kloof tussen relaties en NoSQL-databases over te steken.

Het artikel begint met een korte introductie tot MongoDB, evenals een introductie tot Microsoft’s Entity Framework Core. Vervolgens wordt beschreven hoe u de MongoDB EF Core Provider kunt gebruiken. Na de technische details met enkele basisvoorbeelden zult u een volledig project met MongoB en Entity Framework Core maken zodat u ziet hoe alle dingen samenwerken. Het project zal MongoDB Atlas voorbeeldgegevens gebruiken om een reserveringssysteem voor restaurants aan te maken.

Er is ook een videoversie van dit artikel die u kunt bekijken op de freeCodeCamp.org YouTube-kanaal.

Inleiding tot MongoDB

MongoDB is een populair NoSQL-database ontwikkeld om grote hoeveelheden gegevens te behandelen en hoge prestaties, schaalbaarheid en flexibiliteit te bieden. In tegenstelling tot traditionele relaties databases, slaat MongoDB gegevens op in flexibele, JSON-achtige documenten. De documentgerichte aanpak maakt het mogelijk complexe gegevensstructuren op een meer natuurlijke en intuitieve manier op te slaan.

In MongoDB worden gegevens opgeslagen in collecties, die vergelijkbaar zijn met tabellen in relaties databases, maar zonder een vast schema. Dit betekent dat u documenten met verschillende structuren in dezelfde collectie kunt hebben. Deze flexibiliteit is een van de kenmerkende voorwaarden van het gebruik van MongoDB, vooral bij het behandelen van ongestructureerde of semi-gestructureerde gegevens.

Laten we een voorbeeld bekijken van een MongoDB-document. Veronderstel dat we een collectie hebben genaamd users die informatie over gebruikers in een applicatie opslaat. Hier is wat een typisch document er uit zou kunnen zien:

{
    "_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 dit document hebben we verschillende velden zoals name, email, age en address. Het veld address zelf is een ingebed document dat meerdere subvelden bevat zoals street, city, state en zip. Bovendien is het veld hobbies een array van strings.

Hoewel dit eruitziet als JSON, slaat MongoDB gegevens op in een binaire opslagformaat genaamd BSON (Binary JSON). BSON breidt het JSON-model uit om additionele gegevens typen te bieden, zoals integers, floats, datums en binaire gegevens. Dit binaire formaat is geoptimaliseerd voor prestaties en flexibiliteit, waardoor MongoDB efficiënt gegevens kunt opslaan en terughalen.

Een andere belangrijke functie van MongoDB is zijn mogelijkheid om horizontaal te scalen. Dit betekent dat u uw gegevens kunt verspreiden over meerdere servers, wat het gemakkelijker maakt om grote gegevenssets te beheren en hoge beschikbaarheid te waarborgen. MongoDB ondersteunt ook rijke queries, indexering en aggregaties, waardoor het een krachtige tool is voor een breed scala aan toepassingen.

Bijvoorbeeld, u kunt een query uitvoeren om alle gebruikers te vinden die in een specifieke stad wonen:

db.users.find({ "address.city": "Anytown" })

U kunt ook zoeken naar gebruikers die een specifieke hobby hebben:

db.users.find({ "hobbies": "coding" })

MongoDB wordt breed gebruikt in verschillende industrieën, van e-commerce en contentbeheer tot real-time analytics en IoT-toepassingen. Door zijn flexibiliteit en schaalbaarheid is het een uitstekkende keuze voor moderne applicaties die diverse en dynamische gegevens moeten verwerken.

Nu we een basisbegrip hebben van wat MongoDB is en waarom het populair is, gaan we over naar een ander essentieel gereedschap in onze tech stack: Microsoft’s Entity Framework Core.

Inleiding tot Microsoft’s Entity Framework Core

Entity Framework Core, afgekort tot EF Core, is een moderne object-database-mapper voor .NET. Het laat ontwikkelaars werken met een database door middel van .NET-objecten, waardoor het nodige databaccescode grotendeels overbodig wordt.

EF Core is een lichtgewicht, extensibel en cross-platform versie van de bekende Entity Framework (EF) databeschrijvingstechnologie. Het ondersteunt een breed scala aan database-engines, inclusief SQL Server, SQLite en MongoDB.

Een van de voornaamste voordelen van het gebruik van EF Core is dat ontwikkelaars in een meer intuïtieve en objectgeoriënteerde manier met data kunnen werken. In plaats van raw SQL-query’s schrijven, kun je met uw database door middel van LINQ (Language Integrated Query) en sterke typen klassen interacteren.

Laten we een eenvoudig voorbeeld bekijken. Veronderstel dat we een Product-klasse hebben:

public class Product
{
    public int ProductId { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

Dit is relatief eenvoudig met maar drie velden. Met EF Core kun je een contextklasse maken die een sessie met de database voorstelt en een DbSet bevat voor elke entitytype waarvan u query’s of opslaan wilt:

public class AppDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)   
    {
        optionsBuilder.Use<Your_SQL_Database_function>("YourConnectionStringHere");
    }
}

Deze code definieert een klasse genaamd AppDbContext die erft van Entity Framework Core’s DbContext-klasse. Deze klasse wordt gebruikt om te interageren met de database. Binnen deze klasse is er een DbSet<Product>-eigenschap genaamd Products, die een collectie Product-entiteiten representeert en correspondeert met een tabel genaamd Products in de database. Het OnConfiguring-methode wordt overschreven om de databaseverbinding te configureren, u kunt verschillende databases instellen als databaseprovider. Het gebruikt een optionsBuilder om de verbinding in te stellen met een placeholder voor de echte databaseverbindingsstring. Deze verbindingsstring moet duidelijk worden vervangen door de echte, die de vereiste gegevens bevat om te verbinden met de database. Wanneer u een instantie van AppDbContext maakt in de toepassing, gebruikt het deze configuratie om taken uit te voeren zoals het opslaan of ophalen van Product-entiteiten in de tabel Products.

Met deze setup kunt u CRUD (Create, Read, Update, Delete)-operaties uitvoeren met EF Core. Bijvoorbeeld, om een nieuw product aan de database toe te voegen, kunt u deze code gebruiken.

using (var context = new AppDbContext())
{
    var product = new Product { Name = "Laptop", Price = 999.99M };
    context.Products.Add(product);
    context.SaveChanges();
}

Dit code toont hoe je een nieuw product aan de database kunt toevoegen met behulp van Entity Framework Core. Een instantie van AppDbContext wordt aangemaakt, en binnen dit context wordt een nieuw Product-object met de naam “Laptop” en de prijs 999,99 gemaakt. dit nieuwe product wordt vervolgens toegevoegd aan de Products-collectie die door de AppDbContext wordt beheerd. Uiteindelijk wordt de methode SaveChanges aangeroepen om de wijzigingen op de database op te slaan, wat effectief het nieuwe product toevoegt aan de Products-tabel.

Om producten op te vragen, kun je LINQ gebruiken:

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}");  
    }
}

Dit code toont hoe je de database kunt opvragen met behulp van Entity Framework Core. Een instantie van AppDbContext wordt aangemaakt, en binnen dit context wordt een query gemaakt om alle producten met een prijs van meer dan 500 op te halen. De resultaten worden opgeslagen in een lijst genaamd products. Vervolgens wordt er een lus door elk product in de lijst gelopen, die de naam en de prijs van elk product op het scherm afdrukt.

EF Core neemt de zorg voor dat deze LINQ-query’s worden vertaald in de juiste SQL-commando’s voor uw database, waardoor de toegang tot gegevens eenvoudiger en onderhoudsbaarder wordt.

EF Core ondersteunt ook geavanceerde functies zoals veranderingsvolgen, laag geladen en migraties, die u helpen bij het beheren van schema wijzigingen voor de database over tijd.

In samenleiding maakt EF Core een krachtige ORM die de toegang tot gegevens in .NET-toepassingen simplificeert door gebruik te maken van .NET-objecten en LINQ. Het ondersteunen van meerdere database-engines en zijn extensie maken het een flexibele keuze voor een breed scala aan toepassingen.

Volgend keer zien we hoe de MongoDB EF Core Provider de kloof tussen MongoDB en EF Core overbrugt, ons toestaande om de bekende EF Core patronen te gebruiken met een MongoDB-database.

Hoe de MongoDB EF Core Provider de Kloof Overbrugt

De MongoDB Entity Framework Core Provider is een hulpmiddel dat ontwikkelaars in staat stelt om MongoDB te gebruiken met Entity Framework Core (EF Core), door de flexibiliteit van MongoDB samen te voegen met de bekende API en ontwerpp patronen van EF Core. Deze provider maakt het mogelijk om MongoDB te werken met dezelfde code-first en LINQ-query methodes die u zou gebruiken met relaties databases, waardoor de ontwikkeling gemakkelijker gaat en de leer curve voor hen die al bekend zijn met EF Core wordt verkort.

De MongoDB EF Core Provider overbrugt de kloof tussen MongoDB en EF Core door ondersteuning te bieden voor basis CRUD-operaties, LINQ-queries en ingebedde documenten, onder andere functionaliteiten. Hier zijn enkele kenmerkende mogelijkheden:

  1. Code-First Workflows: U kunt uw gegevens modellen in C# definiëren en EF Core gebruiken om de MongoDB schema te genereren, in plaats van beginnen met het database schema en code ervan te genereren. Dit is bijzonder handig voor ontwikkelaars die hun database structuur liever via code beheren.

  2. CRUD-operaties: De provider ondersteunt basisoperaties voor aanmaken (Create), lezen (Read), bijwerken (Update) en verwijderen (Delete). Bijvoorbeeld, u kunt een nieuw record toevoegen aan de database met behulp van hetzelfde codefragment dat we eerder zagen:

     using (var context = new AppDbContext())
     {
         var product = new Product { Name = "Laptop", Price = 999.99M };
         context.Products.Add(product);
         context.SaveChanges();
     }
    
  3. LINQ-queryondersteuning

    : U kunt LINQ gebruiken om query’s uit te voeren op MongoDB, waardoor u uw bestaande kennis van C# en .NET kunt gebruiken om met de database te interageren.

     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}");
         }
     }
    
  4. Wijzigingsvolgend: De mogelijkheden voor wijzigingsvolgend van EF Core worden ondersteund, die automatisch de detectie en opslaan van wijzigingen aan uw gegevensentiteiten mogelijk maken.

  5. Ingesloten documenten: De provider ondersteunt ingesloten documenten, wat u in staat stelt om gerelateerde gegevens binnen een enkel document op te slaan, wat een algemeen patroon is in MongoDB.

  6. Klassenmapping en serialisatie: Uw C#-klassen worden gemapt naar MongoDB-collecties, met ondersteuning voor verschillende gegevenstypen en serialisatiesettings om er voor te zorgen dat gegevens correct worden opgeslagen.

Data Modelleren en CRUD-operaties met MongoDB Atlas

Nu zal ik u een snel voorbeeld geven hoe u de MongoDB EF Core Provider kunt gebruiken. Maar spoedig zal ik een volledig project maken in Visual Studio Code zodat u alles in context ziet.

In dit gedeelte zullen we ontdekken hoe we gegevensmodellen kunnen definiëren en CRUD-operaties (Create, Read, Update, Delete) kunnen uitvoeren met behulp van de MongoDB Entity Framework Core (EF) Provider en MongoDB Atlas. Deze integratie maakt het mogelijk om de flexibiliteit van MongoDB te benutten samen met de bekende patronen van EF Core.

Instellen van uw Omgeving

Om te beginnen, moet u de noodzakelijke NuGet-pakketten aan uw project toevoegen:

dotnet add package MongoDB.EntityFrameworkCore

Het MS EF Core-pakket en de MongoDB C# Driver worden als afhankelijkheid toegevoegd als u het MongoDB EF Core-providerpakket toevoegt. Deze pakketten maken het mogelijk voor uw toepassing om met MongoDB te interageren via EF Core, met behulp van dezelfde context en entitydefinities die u zou gebruiken bij een relatieve database.

Instellen van MongoDB Atlas

Om CRUD-operaties uit te voeren, moet u een MongoDB Atlas-cluster instellen en uw toepassing eraan verbinden.

Hier zijn de stappen. Merk op dat we deze in detail zullen behandelen bij het maken van het project spoedig.

  1. Maak een MongoDB Atlas Account: Meld u aan voor een gratis account op MongoDB Atlas.

  2. Een cluster maken: Maak een nieuw cluster. MongoDB Atlas biedt een gratis laag die perfect is voor ontwikkeling en kleinschalige toepassingen.

  3. Verkrijg verbindingsreeks: Verkrijg uw verbindingsreeks van het MongoDB Atlas dashboard. Het ziet er iets als dit uit:

     mongodb+srv://<username>:<password>@cluster0.mongodb.net/myFirstDatabase?retryWrites=true&w=majority
    

Data model definiëren

Defineer een klasse die als model voor uw entiteit wordt gebruikt. Voor dit voorbeeld zal hij een Klant klasse aanmaken:

public class Customer
{
    public ObjectId Id { get; set; }
    public String Name { get; set; }
    public String Order { get; set; }
}

Deze Klant klasse representeert de structuur van de documenten die in de MongoDB collectie worden opgeslagen.

Maak een DB Context Klasse

Om Entity Framework Core te beginnen, maak een contextklasse die van DBContext afgeleid is. HetDbContext afgeleide klasseobject representeert een database sessie en wordt gebruikt om query’s uit te voeren en voorwerpen van uw entiteiten op te slaan.

De DBContext klasse exposeert DBSet eigenschappen die de entiteiten specificeren die u kunt interacteren terwijl u dat context gebruikt.

Dit voorbeeld maakt een instantie van een DBContext afgeleide klasse en specificeert het Customer object als een DBSet eigenschap:

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

Met de MongoDB EF Provider kun je een code-first workflow gebruiken. Dit betekent dat je eerst je klassen definieert, en dat EF Core de creatie en beheer van de onderliggende MongoDB schema’s op zich neemt. Dit is bijzonder handig voor MongoDB, die geen schema afdwingt, wat flexibele en dynamische gegevensstructuren toestaat.

Gebruik MongoDB

Nadat we een DBContext klasse hebben aangemaakt, moeten we een DbContextOptionsBuilder object aanmaken en zijn UseMongoDB() method aanroepen. Deze methode neemt twee parameters: een MongoClient instantie en de naam van de database waarin de collecties die u werkt met zijn opgeslagen.

De UseMongoDB() methode retourneert een DbContextOptions object. Geef de Options eigenschap van dit object aan de constructor van uw DBContext klasse.

var mongoClient = new MongoClient("<Your MongoDB Connection URI>");

var dbContextOptions =
    new DbContextOptionsBuilder<MyDbContext>().UseMongoDB(mongoClient, "<Database Name");  

var db = new MyDbContext(dbContextOptions.Options);

CRUD Operations

Laten we nu zien hoe de CRUD operaties gecodeerd kunnen worden. We zullen ons specifiek op elke operatie focusen.

Create Operation

Om een nieuw document in MongoDB aan te maken, gebruik je de Add methode op de DbSet en roep SaveChanges aan. dit is een voorbeeld van het aanmaken van een nieuwe klant:

using (var context = new MyDbContext(options))
{
    var customer = new Customer { Name = "Beau Carnes", Order = "Laptop" };
    context.Customers.Add(customer);
    context.SaveChanges();
}

Dit code creëert een nieuwe Customer instantie en voegt hem toe aan de Customers collectie. De methode SaveChanges slaat de nieuwe klant op in de MongoDB database.

Lezen Operatie

Om documenten uit de MongoDB-verzameling te lezen, kun je LINQ-query’s op de DbSet gebruiken. Dit is een voorbeeld van het ophalen van alle klanten:

using (var context = new MyDbContext(options))
{
    var customers = context.Customers.ToList();
    foreach (var customer in customers)
    {
        Console.WriteLine($"Customer: {customer.Name}, Order: {customer.Order}"); 
    }
}

Dit code haalt alle klanten uit de Customers-verzameling op en toont hun details.

Bijwerken Operatie

Om een bestaand document bij te werken, haalt u het document op, passt uw eigenschappen aan en roept u SaveChanges aan. Dit is een voorbeeld van het bijwerken van een klantenbestelling:

using (var context = new MyDbContext(options))
{
    var customer = context.Customers.FirstOrDefault(c => c.Name == "Beau Carnes"); 
    if (customer != null)
    {
        customer.Order = "Smartphone";
        context.SaveChanges();
    }
}

Dit code zoekt de klant “Beau Carnes” en update hun bestelling naar “Smartphone”.

Verwijderen Operatie

Om een document te verwijderen, haalt u het document op, verwijdert u het uit de DbSet en roept u SaveChanges aan. Dit is een voorbeeld van het verwijderen van een klant:

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();
    }
}

Dit code zoekt de klant “Beau Carnes” en verwijdert hen uit de Customers-verzameling.

Wijzigingsvolgorde

EF Core’s vermogens voor wijzigingsvolgorde worden volledig ondersteund, wat efficiente updates aan documenten mogelijk maakt. Wanneer u een entiteit aanpast en SaveChanges aanroept, genereert EF Core de nodige MongoDB-commando’s om alleen de gewijzigde velden bij te werken.

Door de MongoDB EF Provider te gebruiken, kun je de flexibele documentenmodel van MongoDB gemakkelijk integreren met de krachtige ORM-mogelijkheden van EF Core, waardoor .NET-ontwikkelaars een krachtige toolset krijgen om moderne applicaties te bouwen.

Tutorial

Nu laten we alles samenbrengen om een reserveringssysteem voor restaurants te maken.

Vereisten

Om mee te groeien met dit handleiding, heb je enkele dingen nodig:

Maak het project

ASP.NET Core is een erg flexibel webframeWork, dat het mogelijk maakt verschillende typen webapplicaties te koloniseren met kleine verschillen op het gebied van hun UI of structuur. Voor deze handleiding zullen we een MVC-project maken dat gebruik zal maken van statische bestanden en controllers. Er zijn andere typen van voorgevel die u kunt gebruiken, zoals React, maar MVC met .cshtml-weergaven is het meest gebruikte. Om het project te maken, zullen we de .NET CLI gebruiken:

dotnet new mvc -o RestRes

Omdat we de CLI gebruikten, is het gemakkelijker, maar het maakt alleen de csproj-bestanden en niet het oplossingsbestand dat ons toelaat om ze te openen in Visual Studio, dus we zullen dat aanpassen.

cd RestRes
dotnet new sln
dotnet sln .\RestRes.sln add .\RestRes.csproj

Voeg de NuGet-pakketten toe

Nu we een nieuw project hebben aangemaakt, zullen we graag doorgaan met het toevoegen van de vereiste NuGet-pakketten. Of door middel van de NuGet Package Manager of door middel van het onderstaande .NET CLI-commando, voeg het MongoDB MongoDB.EntityFrameworkCore-pakket toe.

dotnet add package MongoDB.EntityFrameworkCore

Maak de modellen

Voordat we kunnen beginnen met het implementeren van de nieuwe pakketten die we net toegevoegd hebben, moeten we de modellen creëren die de entiteiten voor ons restaurantreserveringssysteem representeren, die opgeslagen zullen worden in MongoDB Atlas als documenten. In de volgende subsecties zullen we de volgende modellen aanmaken:

  • Restaurant

  • Reservation

  • MongoDBSettings

Restaurant

Voordat we beginnen met ons restaurantmodel, dat de restaurants representeert die in ons systeem kunnen worden gereserveerd, moeten we eerst een nieuw bestand in de Modellenmap aanmaken en dat noemen Restaurant.cs.

  1. Create a new file in the Models folder called Restaurant.cs.

  2. 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; }

    }
}

Het collection attribute voor de klasse vertelt de applicatie welke collectie binnen de database we gebruiken. Dit maakt het mogelijk om verschillende namen of hoofdletters tussen onze klasse en onze collectie te kiezen, indien nodig.

Reservation

We hebben ook een reserveringsklasse nodig om elke reservering die we in ons systeem nemen te representeren.

  1. Create a new file inside the Models folder called Reservation.cs.

  2. 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

Hoewel het geen document zal zijn in onze database, hebben we een modelklasse nodig om onze MongoDB-gerelateerde instellingen op te slaan zodat ze over de hele applicatie kunnen worden gebruikt.

  1. Maak in de Models map een nieuw bestand aan genaamd MongoDBSettings.cs.

  2. Voeg het volgende code toe:

namespace RestRes.Models
{
  public class MongoDBSettings
  {
      public string AtlasURI { get; set; }
      public string DatabaseName { get; set; }
  }
}

Instellen van EF Core

Dit is de spannende deel. We gaan beginnen met het implementeren van EF Core en profiteren van de nieuwe MongoDB-provider. Als je al aan het werk bent met EF Core, zal sommige onderdelen voor je bekend zijn.

RestaurantReservationDbContext

  1. Maak een Services map aan en maak daarin een bestand aan genaamd RestaurantReservationDbContext.cs.

  2. Vervang de code binnen het namespace door het volgende:

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>();
        }
    }
}

Als je gevoelens hebt voor EF Core, zal dit bekend zijn. De klasse breidt de DbContext uit en we maken eigenschappen voor DbSet die de modellen opslaan die ook in de database aanwezig zijn. We overschrijven ook de methode OnModelCreating. U zult waarschijnlijk merken dat, in tegenstelling tot wanneer u SQL Server gebruikt, we geen .ToTable() bellen. We konden ToCollection bellen in plaats daarvan, maar dat is hier niet nodig omdat we de verzameling specificeren door attributen op de klassen te gebruiken.

Voeg de verbindingsstring en databasegegevens toe aan appsettings

Vroeger hebben we een MongoDBSettings-model aangemaakt, en nu moeten we de waarden toevoegen waarnaar de eigenschappen in onze appsettings mapten.

  1. In zowel appsettings.json als appsettings.Development.json, voeg het volgende nieuwe gedeelte toe:

      "MongoDBSettings": {
        "AtlasURI": "mongodb+srv://<gebruikersnaam>:<wachtwoord>@<url>",
        "DatabaseName": "restaurants"
      }
    
  2. Vervang de Atlas URI door uw eigen connectie-string van Atlas.

Program.cs bijwerken

Nu onze modellen en DbContext zijn geconfigureerd, is het tijd om ze toe te voegen aan onze program.cs-bestand.

Na de bestaande regel builder.Services.AddControllersWithViews();, voeg het volgende code toe:

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 ?? ""));

Services aanmaken

Nu is het tijd om de services toe te voegen die we zullen gebruiken om via de RestaurantBookingDbContext die we hebben aangemaakt, met de database te communiceren. Voor elke service zal hij een interface en de klasse die deze implementeert aanmaken.

IRestaurantService en RestaurantService

De eerste interface en service die we zullen implementeren, is voor het uitvoeren van de CRUD-operaties op de collectie restaurants. Dit wordt de repository patronen genoemd. U zult mensen zien die direct met de DbContext communiceren. Maar de meeste mensen gebruiken dit patronen, waarom we het hier bijdragen.

  1. Als u nog niet heeft, maak een Services map aan om onze nieuwe klassen op te slaan.

  2. Maak een IRestaurantService interface en voeg het volgende code voor de methodes toe die we zullen implementeren:

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);
    }
}
  1. Maak een RestaurantService klasse bestand.

  2. Bijwerken de declaratie van de RestaurantService klasse zodat hij de IRestaurantService die we net hebben aangemaakt, implementeert:

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 en ReservationService

Volgend is ons IReservationService en ReservationService.

Maak het IReservationService interface en voeg de volgende methodes toe:

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);
    }
}

Maak de ReservationService klasse en vervang uw klasse door het volgende code dat alle methodes implementeert:

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);
        }

    }
}

Dit code is erg vergelijkbaar met het code voor de RestaurantService klasse, maar voor reserveringen in plaats daarvan.

Het toevoegen aan Dependency Injection

Het laatste stukje voor de services is om ze aan het afhankelijkheidspunt toe te voegen.

Inside Program.cs, voeg je de volgende code toe na de code die we er eerder aan hebben toegevoegd:

builder.Services.AddScoped<IRestaurantService, RestaurantService>();
builder.Services.AddScoped<IReservationService, ReservationService>();

View models maken

Voordat we de front end implementeren, moeten we de view models toevoegen die als boodschapper fungeren tussen onze front en back ends waar nodig. Zelfs al is onze applicatie relatief eenvoudig, is het implementeren van de view model nog steeds een goed voorbeeld omdat het de delen van de app decoupeert.

RestaurantListViewModel

De eerste die we toevoegen is de RestaurantListViewModel. Dit zal later gebruikt worden als model voor onze Razor pagina voor het weergeven van restaurants in onze database.

  1. Maak een nieuwe map in de root van het project aan die heet ViewModels.

  2. Voeg een nieuw bestand aan toe genaamd RestaurantListViewModel.cs.

  3. Voeg het volgende code toe:

using RestRes.Models;

namespace RestRes.ViewModels
{
    public class RestaurantListViewModel
    {        
        public IEnumerable<Restaurant>? Restaurants { get; set; }
    }
}

RestaurantAddViewModel

We willen ook een view model die gebruikt kan worden door de later toe te voegen Add weergave.

  1. Binnen de ViewModels map, maak een nieuw bestand aan genaamd RestaurantAddViewMode.cs.

  2. Toevoegen:

using RestRes.Models;

namespace RestRes.ViewModels
{
    public class RestaurantAddViewModel
    {
        public Restaurant? Restaurant { get; set; } 
    }
}

ReservationListViewModel

Nu willen we iets heel vergelijkbaars voor reserveringen doen, beginnend met ReservationListViewModel.

  1. Maak een nieuw bestand in de ViewModels map aan genaamd ReservationListViewModel.cs.

  2. Toevoegen:

using RestRes.Models;

namespace RestRes.ViewModels
{
    public class ReservationListViewModel
    {
        public IEnumerable<Reservation>? Reservations { get; set; }
    }
}

ReservationAddViewModel

Tot slot hebben we ons ReservationAddViewModel.

Maak het bestand aan en voeg dit code toe:

using RestRes.Models;

namespace RestRes.ViewModels
{
    public class ReservationAddViewModel
    {
        public Reservation? Reservation { get; set; }
    }
}

Toevoegen aan _ViewImports

Later zullen we in de views referenties aan onze models en viewmodels toevoegen. Om voor de applicatie te weten welke ze zijn, moeten we referenties aan hen toevoegen in het _ViewImports.cshtml bestand binnen de Views map.

Er zal al wat referenties aanwezig zijn, inclusief TagHelpers, dus we willen referenties aan onze .Models en .ViewModels mappen toevoegen. Dus zou de bovenkant van het bestand er ongeveer zo uit moeten zien:

@using RestRes
@using RestRes.Models
@using RestRes.ViewModels

Controller’s maken

Nu we de backend implementatie en de te gebruiken viewmodels hebben, kunnen we beginnen aan de voorkant. We zullen twee controllers maken: een voor Restaurant en een voor Reservation.

RestaurantController

De eerste controller die we toevoegen is voor het restaurant.

  1. In de bestaande Controllers map, voeg een nieuw controllerbestand toe genaamd RestaurantController.cs. Als u Visual Studio gebruikt, kies dan de MVC Controller – Lege controller sjabloon.

  2. Voeg dit code toe:

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

Nu voor het reserveringscontroller. Dit is erg vergelijkbaar met de RestaurantController, maar het heeft een verwijzing naar zowel het restaurant als de reserveringsservice, want we moeten een restaurant associëren met een reservering. Dit omdat het momenteel de EF Core Provider geen ondersteuning biedt voor relaties tussen entiteiten, dus kunnen we entiteiten op een andere manier relateren.

  1. Maak een andere lege MVC Controller bestand aan genaamd ReservationController.cs.

  2. Plak het volgende code:

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);
        }
    }
}

Creating the views

Nu we de back end en de controllers voor onze restaurantreserveringssysteem klaar hebben met de endpoints, is het tijd om de views uit te voeren. Dit zal gebeuren met behulp van Razor pagina’s. U zult ook verwijzingen naar klassen uit Bootstrap zien, want dit is de CSS-framework dat standaard meekomt met MVC-toepassingen. We zullen views leveren voor de CRUD-bewerkingen voor zowel lijsten als reserveringen.

Listing Restaurants

We beginnen met een weergave die mapte naar de root van /Restaurant, die gebruikelijk naar de Index methode die we geïmplementeerd hadden zou kijken.

ASP.NET Core MVC gebruikt een conventiepatroon waarbij u de .cshtml bestanden naar de naam van de endpoint/methode vernoemt en ze binnen een map zitten die naar hun controller vernoemd is.

  1. Binnen de Views map, maak een nieuwe submap genaamd Restaurant.

  2. Binnen die Restaurant map, voeg een nieuwe weergave toe door een bestand te maken genaamd Index.cshtml. Als u de beschikbare templates gebruikt, kiest u Razor Weergave – Leeg. Noem de weergave Index.

  3. Voeg dit code toe:

@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>

Laten we nu de standaard route van Home naar /Restaurant bijwerken.

In Program.cs, binnen app.MapControllerRoute, vervang de patronenregel door de volgende:

pattern: "{controller=Restaurant}/{action=Index}/{id?}");

Als we dit nu uitvoerden, zouden de knoppen leiden tot 404’s omdat we ze nog niet geïmplementeerd hebben. Laten we dat dus nu doen.

Restaurants toevoegen

We beginnen met het formulier voor het toevoegen van nieuwe restaurants.

  1. Voeg een nieuwe, lege Razor Weergave toe binnen de Restaurant submap genaamd Add.cshtml.

  2. Voeg het volgende code toe:

@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 bewerken

Het code voor de bewerkingspagina is bijna identiek aan dat voor toevoegen, maar het gebruikt het Restaurant-model omdat het het restaurant dat wordt doorgegeven zal gebruiken om de formulier voor bewerkingen vooraf te vullen.

  1. Voeg nog een andere weergave toe binnen de submap Restaurants met de naam Edit.cshtml.

  2. Voeg het volgende code toe:

@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 verwijderen

De laatste pagina die we moeten implementeren is de pagina die wordt aangeroepen wanneer de knop Verwijderen wordt geklikt.

  1. Maak een nieuwe lege Weergave aan genaamd Delete.cshtml.

  2. Voeg het volgende code toe:

@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>

Reservaties overzichten

We hebben de weergaves voor de restaurants toegevoegd, dus nu zullen we de weergaves voor de reservaties toevoegen, beginnend met het overzichten van bestaande reservaties.

  1. Maak een nieuwe map binnen de Map Weergaves genaamd Reservation.

  2. Maak een nieuwe lege weergavebestand aan genaamd Index.cshtml.

  3. Voeg het volgende code toe om de reservaties weer te geven, indien er enige bestaan:

@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>   

}

Reservaties toevoegen

Reserveringen toevoegen zijn erop af.

  1. Maak een lege weergave aan genaamd Add.cshtml.

  2. Voeg het volgende code toe:

@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>

Bewerken van reserveringen

Bewerken van reserveringen is erop af.

  1. Maak een lege weergave aan genaamd Edit.cshtml.

  2. Voeg het volgende code toe:

@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>

Verwijderen van reserveringen

Verwijderen van reserveringen is erop af.

  1. Maak een lege weergave aan genaamd Delete.cshtml.

  2. Voeg het volgende code toe:

@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>

Bijwerken van NavBar

Het laatste dat we moeten toevoegen is het bijwerken van de navigatiebalk van de applicatie zodat we gemakkelijk kunnen schakelen tussen restaurants en reserveringen.

Navigeer naar het bestand op Views/Shared/_Layout.cshtml. Zoek naar de div met de klasse navbar-collapse. Verwijder de hele sectie en voeg het volgende code toe:

<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 van onze applicatie

We hebben nu een functionele applicatie die gebruik maakt van het nieuwe MongoDB Provider voor EF Core. Nu is het tijd om het allemaal te testen en onze endpoints te bezoeken om erop te controleren of het allemaal werkt.

Voer in de terminal het volgende commando uit:

dotnet run

Probeer restaurants te bewerken en reserveringen toe te voegen. U kunt vervolgens naar de pagina van de MongoDB Atlas database navigeren en zien dat uw wijzigingen in de database worden weergegeven.

Geavanceerde MongoDB-operaties: Atlas Search en Vector Search

De EF Core-provider is gebouwd op de MongoDB C# Driver. Aangezien we al toegang hebben tot de MongoClient bij het maken van de DbContext, laat dit ons toe om geavanceerde MongoDB-operaties uit te voeren, zoals Atlas Search en Vector Search. Deze functionaliteiten versterken de mogelijkheden van uw toepassing door mogelijke zoekfunctionaliteiten te implementeren terwijl u nog steeds de bekende EF Core-framework gebruikt.

Atlas Search is een full-text zoekmachine geleverd door MongoDB Atlas. Het stelt u in staat om complexe zoekopdrachten uit te voeren op uw MongoDB-gegevens. Met Atlas Search kunt u functies implementeren zoals automatisch aanvullen, facettensearch en sorteren op relevantie.

Om Atlas Search met de EF Core Provider te gebruiken, volg deze stappen:

  1. Indexen in MongoDB Atlas instellen:

    • Ga naar uw MongoDB Atlas cluster.

    • Navigeer naar de “Zoeken”-tab en maak een nieuwe index aan op uw collectie. Definieer de velden die u zoekbaar wilt maken.

  2. Definieer zoekbare velden in uw modellen : Zorg er voor dat de velden die u wilt zoeken in uw C#-modellen correct zijn gedefinieerd. Hier is een voorbeeld van de definitie van een Productmodel.

     public class Product
     {
         public ObjectId Id { get; set; }
         public string Name { get; set; }
         public string Description { get; set; }
         public decimal Price { get; set; }
         public string Category { get; set; }
     }
    
  3. Zoekopdrachten uitvoeren: Gebruik de mogelijkheden van de MongoDB .NET Driver om tekstzoekopdrachten uit te voeren. Aangezien EF Core zelf de MongoDB-specifieke zoeksyntaxis niet rechtstreeks ondersteunt, moet je de driver gebruiken in combinatie met EF Core. Hier is een voorbeeld:

     using MongoDB.Driver;
     using MongoDB.Driver.Linq;
    
     var client = new MongoClient("your-mongodb-connection-string");
     var database = client.GetDatabase("your-database-name");
     var verzameling = database.GetCollection<Product>("Producten");
    
     var searchResult = collection.Aggregate()
         .Match(Builders<Product>.Filter.Tekst("zoekterm")).
         .ToList();
    

Dit voorbeeld laat zien hoe u een tekstzoekopdracht uitvoert op de collectie Products. Het Text filter helpt bij het zoeken over alle geïndexeerde velden die zijn gedefinieerd in uw Atlas Search-index.

Vector Zoeken in MongoDB wordt gebruikt om documenten op basis van vectorovereenkomst te zoeken, wat bijzonder handig is voor toepassingen die machine learning, aanbevelingen en natuurlijk taalverwerking gebruiken. Vector Zoeken laat u documenten aanvallen met vectors die de representatie zijn van tekst, afbeeldingen of andere hoge-dimensionale data.

  1. Maak en bewaren Vector: Begin door te controleren of uw documenten vector bevatten. U zou wellicht gegevens moeten voorbereiden om deze vectors te genereren met behulp van machine learning-modellen.

  2. Indexeer vectoren in MongoDB Atlas: Maak een speciale index op het vectorveld in MongoDB Atlas aan om efficiënte vectorovereenkomstzoeken mogelijk te maken.

  3. Vectorkoorden doorvoeren in zoekopdrachten: gebruik de MongoDB .NET Driver om op basis van vectorovereenkomst te zoeken.

Integreren met EF Core

Hoewel de MongoDB EF Core Provider CRUD-operaties simplifyert, zijn er enkele geavanceerde functionaliteiten zoals Atlas Search en Vectorkoorden zoeken nodig om direct de MongoDB .NET Driver te gebruiken. U kunt deze taken toch binnen uw EF Core-gebaseerde toepassing integreren door de driver voor zoekfuncties te gebruiken en EF Core voor andere gegevensbeheer taken.

door de combinatie van EF Core en de geavanceerde functionaliteiten van MongoDB, kunt u krachtige en flexibele toepassingen bouwen die de beste kanten van beide werelden benutten—gestructureerde gegevenstoegang patronen van EF Core en de krachtige zoekcapabilities van MongoDB Atlas.