O Entity Framework Core é um popular ORM (Object-Relational Mapper) para aplicações .NET, que permite que os desenvolvedores trabalhem com bancos de dados usando objetos .NET. Ele pode ser usado com muitos tipos de bancos de dados, incluindo o MongoDB.
Neste artigo, você aprenderá como usar o Entity Framework Core com o MongoDB. Este artigo abrange os fundamentos, explica os benefícios e fornece um tutorial passo a passo. Se você estiver começando com MongoDB ou Entity Framework Core, ou apenas procurando integrar essas ferramentas em seus projetos .NET, este guia o ajudará a atingir a ligação entre bancos de dados relacionais e NoSQL.
O artigo começa com uma breve Introdução ao MongoDB bem como uma Introdução ao Entity Framework Core da Microsoft. Em seguida, ele cover como usar o provedor MongoDB EF Core. Depois de passar por detalhes técnicos com alguns exemplos básicos, você criará um projeto completo com MongoB e Entity Framework Core para ver como tudo funciona juntos. O projeto usará dados de exemplo do MongoDB Atlas para criar um sistema de reservas de Restaurante.
Há também uma versão de vídeo deste artigo que você pode assistir no canal YouTube do freeCodeCamp.org.
Introdução ao MongoDB
O MongoDB é um popular banco de dados NoSQL projetado para lidar com grandes volumes de dados e fornecer alta performance, escalabilidade e flexibilidade. Ao contrário dos bancos de dados relacionais tradicionais, o MongoDB armazena dados em documentos flexíveis, semelhantes a JSON. Este paradigma de documento orientado permite que dados estruturados complexos sejam armazenados de uma maneira mais natural e intuitiva.
No MongoDB, dados são armazenados em coleções, que são semelhantes a tabelas em bancos de dados relacionais mas sem um esquema fixo. Isso significa que você pode ter documentos com estruturas diferentes na mesma coleção. Esta flexibilidade é uma das vantagens chave de usar o MongoDB, especialmente quando se trata de dados não estruturados ou semi-estruturados.
Vamos olhar por um exemplo de um documento MongoDB. Imagine que temos uma coleção chamada users
que armazena informações sobre usuários em um aplicativo. Aqui é o que um documento típico pode parecer:
{
"_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"]
}
Neste documento, temos vários campos como name
, email
, age
, e address
. O campo address
em si é um documento embutido que contém vários subcampos como street
, city
, state
, e zip
. Além disso, o campo hobbies
é um array de strings.
Enquanto isso parece JSON, o MongoDB armazena dados em um formato binário chamado BSON (Binary JSON). O BSON estende o modelo JSON para fornecer tipos de dados adicionais, como inteiros, flutuantes, datas e dados binários. Este formato binário é otimizado para performance e flexibilidade, permitindo que o MongoDB armazene e recupere dados com eficiência.
Uma outra funcionalidade importante do MongoDB é sua capacidade de dimensionar horizontalmente. Isso significa que você pode distribuir seus dados por vários servidores, fazendo com que seja fácil gerenciar grandes conjuntos de dados e garantir alta disponibilidade. O MongoDB também suporta consultas rica, indexação e agregação, tornando-se uma ferramenta poderosa para uma ampla gama de aplicações.
Por exemplo, você pode executar uma consulta para encontrar todos os usuários que moram em uma cidade específica:
db.users.find({ "address.city": "Anytown" })
Você pode encontrar usuários que têm um hobby específico:
db.users.find({ "hobbies": "coding" })
O MongoDB é amplamente usado em várias indústrias, desde o e-commerce e o gerenciamento de conteúdo até a análise em tempo real e as aplicações de Internet das Coisas (IoT). sua flexibilidade e escalabilidade o tornam uma escolha excelente para aplicações modernas que precisam lidar com dados diversos e dinâmicos.
Agora que nós temos um entendimento básico de o que é o MongoDB e por que é popular, vamos passar para outra ferramenta essencial na nossa stack tecnológica: o Entity Framework Core da Microsoft.
Introdução ao Entity Framework Core da Microsoft
O Entity Framework Core, frequentemente abreviado como EF Core, é um moderno objeto-mapeamento de banco de dados para .NET. Permite que desenvolvedores trabalhem com um banco de dados usando objetos .NET, eliminando a necessidade de a maioria do código de acesso a dados que os desenvolvedores normalmente precisam escrever.
O EF Core é uma versão leve, extensível e multiplataforma da popular tecnologia de acesso a dados Entity Framework (EF). Ele suporta uma variedade de motores de banco de dados, incluindo SQL Server, SQLite e MongoDB.
Um dos principais benefícios de usar EF Core é que ele permite que desenvolvedores trabalhem com dados de uma maneira mais intuitiva e orientada a objetos. Em vez de escrever consultas SQL brutas, você pode interagir com seu banco de dados usando LINQ (Language Integrated Query) e classes fortemente tipadas.
Vamos olhar para um exemplo básico. Imaginemos que temos uma classe Product
:
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
Isso é muito simples com apenas três campos. Usando o EF Core, você pode criar uma classe de contexto que representa uma sessão com o banco de dados e inclui um DbSet
para cada tipo de entidade que você quer consultar ou salvar:
public class AppDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.Use<Your_SQL_Database_function>("YourConnectionStringHere");
}
}
Este código define uma classe chamada AppDbContext
que herda da classe DbContext
do Entity Framework Core. Esta classe é usada para interagir com o banco de dados. Dentro desta classe, há uma propriedade DbSet<Product>
chamada Products
, que representa uma coleção de entidades Product
e corresponde a uma tabela chamada Products
no banco de dados. O método OnConfiguring
é sobrescrito para configurar a conexão com o banco de dados, você pode especificar vários bancos de dados como provedor de banco de dados. Esse método usa um optionsBuilder
para configurar a conexão com um marcador de posição para a string de conexão de banco de dados real. Evidentemente, essa string de conexão deve ser substituída pela real contendo os detalhes necessários para se conectar ao banco de dados. Quando você cria uma instância de AppDbContext
na aplicação, ela usa essa configuração para realizar operações como consultar ou salvar entidades Product
na tabela Products
.
Com esta configuração, você pode realizar operações CRUD (Criar, Ler, Atualizar, Excluir) usando o EF Core. Por exemplo, para adicionar um novo produto ao banco de dados, você pode usar este código.
using (var context = new AppDbContext())
{
var product = new Product { Name = "Laptop", Price = 999.99M };
context.Products.Add(product);
context.SaveChanges();
}
Este código demonstra como adicionar um novo produto à base de dados usando Entity Framework Core. Uma instância de AppDbContext
é criada, e dentro deste contexto, um novo objeto Product
com o nome “Laptop” e o preço de 999.99 é instanciado. Este novo produto é então adicionado à coleção Products
gerenciada pelo AppDbContext
. Finalmente, o método SaveChanges
é chamado para salvar as mudanças na base de dados, inserindo efetivamente o novo produto na tabela Products
.
Para consultar produtos, você pode usar LINQ:
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}");
}
}
Este código demonstra como consultar a base de dados usando Entity Framework Core. Uma instância de AppDbContext
é criada, e dentro deste contexto, uma consulta é feita para recuperar todos os produtos com um preço superior a 500. Os resultados são armazenados em uma lista chamada products
. Em seguida, um laço percorre cada produto na lista, imprimindo o nome e o preço de cada produto no console.
EF Core cuida de traduzir essas consultas LINQ em comandos SQL apropriados para sua base de dados, tornando a acesso a dados simples e mais manutenível.
EF Core também suporta recursos avançados como acompanhamento de mudanças, carregamento à vontade e migrações, o que ajuda a gerenciar mudanças no esquema de banco de dados ao longo do tempo.
Em resumo, EF Core é uma potente ORM que simplifica o acesso a dados em aplicações .NET, permitindo que você trabalhe com seus dados usando objetos .NET e LINQ. Seu suporte a vários motores de banco de dados e sua extensibilidade o tornam uma escolha versátil para uma ampla gama de aplicações.
Aqui, veremos como o provedor MongoDB para EF Core conecta a brecha entre MongoDB e EF Core, permitindo que use os padrões familiares de EF Core com um banco de dados MongoDB.
Como o Provedor MongoDB para EF Core Conecta a Brecha
O Provedor MongoDB para Entity Framework Core (EF Core) é uma ferramenta que permite que os desenvolvedores usem MongoDB com Entity Framework Core (EF Core), combinando a flexibilidade de MongoDB com os padrões de API e de projeto familiares de EF Core. Este provedor permite que você trabalhe com MongoDB usando as mesmas metodologias de primeiro código e consultas LINQ que você usaria com bancos de dados relacionais, simplificando o desenvolvimento e reduzindo a curva de aprendizagem para aqueles que estão familiarizados com EF Core.
O Provedor MongoDB para EF Core conecta a brecha entre MongoDB e EF Core ao suportar operações básicas de CRUD, consultas LINQ e documentos aninhados, entre outras funcionalidades. Aqui estão algumas capacidades chave:
-
Fluxos Primeiro Código: Você pode definir seus modelos de dados em C# e usar o EF Core para gerar o esquema do MongoDB, em vez de começar com o esquema do banco de dados e gerar código a partir dele. Isso é particularmente útil para desenvolvedores que preferem gerenciar sua estrutura de banco de dados através de código.
-
Operações CRUD: O provedor suporta operações básicas de criar, ler, atualizar e excluir. Por exemplo, você pode adicionar um novo registro à base de dados usando o mesmo código que vimos anteriormente:
using (var context = new AppDbContext()) { var produto = new Produto { Nome = "Laptop", Preço = 999.99M }; context.Produtos.Add(produto); context.SaveChanges(); }
-
Suporte a Consultas LINQ
: Você pode usar LINQ para realizar consultas contra o MongoDB, permitindo que você aproveite seu conhecimento existente sobre C# e .NET para interagir com o banco de dados.
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}"); } }
-
Rastreio de Mudanças: As capacidades de rastreamento de mudanças do EF Core são suportadas, permitindo a detecção automática e o salvamento de mudanças feitas em suas entidades de dados.
-
Documentos Embutidos: O provedor suporta documentos embutidos, permitindo que você armazene dados relacionados em um único documento, o que é um padrão comum no MongoDB.
-
Mapeamento de Classes e Serialização: As suas classes C# são mapeadas para coleções do MongoDB, com suporte para vários tipos de dados e configurações de serialização para garantir que dados são armazenados corretamente.
Modelagem de Dados e Operações CRUD com o MongoDB Atlas
Agora vamos passar por um exemplo rápido de como usar o provedor MongoDB EF Core. Mas em breve, vamos criar um projeto completo no Visual Studio Code para que você veja tudo em contexto.
Criaremos um ambiente de desenvolvimento com os seguintes passos:
Configuração do seu ambiente
Para começar, você precisa adicionar os pacotes NuGet necessários ao seu projeto:
dotnet add package MongoDB.EntityFrameworkCore
O pacote MS EF Core e o Driver C# para MongoDB são adicionados como dependências quando você adiciona o pacote provedor MongoDB EF Core. Esses pacotes permitem que sua aplicação interaja com o MongoDB através do EF Core, usando o mesmo contexto e definições de entidade que você usaria com um banco de dados relacional.
Configuração do MongoDB Atlas
Antes de executar operações CRUD, você precisa configurar um cluster do MongoDB Atlas e conectar sua aplicação a ele.
Aqui estão os passos. Note que vamos passar por eles em detalhe quando criarmos o projeto em breve.
-
Crie uma conta no MongoDB Atlas: Cadastre-se gratuitamente em MongoDB Atlas.
-
Criar um Cluster: Configure um novo cluster. O MongoDB Atlas oferece uma camada gratuita perfeita para desenvolvimento e aplicações de pequeno porte.
-
Obter String de Conexão: Obtenha sua string de conexão do painel do MongoDB Atlas. Ela terá algo como isto:
mongodb+srv://<username>:<password>@cluster0.mongodb.net/myFirstDatabase?retryWrites=true&w=majority
Modelando os Dados
Defina uma classe para usar como modelo para sua entidade. Para este exemplo, vamos criar uma classe Cliente
:
public class Customer
{
public ObjectId Id { get; set; }
public String Name { get; set; }
public String Order { get; set; }
}
Esta classe Cliente
representa a estrutura dos documentos armazenados na coleção MongoDB.
Criar uma Classe de Contexto de BD
Para começar a usar o Entity Framework Core, crie uma classe de contexto que herde de DBContext. A instância da classe derivada DbContext
representa uma sessão de banco de dados e é usada para consultar e salvar instâncias de suas entidades.
A classe DBContext
expõe propriedades DBSet
que especificam as entidades com as quais você pode interagir enquanto usa esse contexto.
Este exemplo cria uma instância de uma classe derivada de DBContext
e especifica o objeto Customer
como uma propriedade DBSet
:
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");
}
}
Workflow Code-First
Com o MongoDB EF Provider, você pode usar um workflow code-first. Isso significa que você define suas classes primeiro, e o EF Core cuidará da criação e gestão do esquema subjacente do MongoDB. Isso é particularmente útil para o MongoDB, que não impõe um esquema, permitindo estruturas de dados flexíveis e dinâmicas.
Usar MongoDB
Uma vez que criamos uma classe DBContext
, precisamos construir um objeto DbContextOptionsBuilder
e chamar seu método UseMongoDB()
. Este método leva dois parâmetros: uma instância de MongoClient
e o nome do banco de dados que armazena as coleções com as quais você está trabalhando.
O método UseMongoDB()
retorna um objeto DbContextOptions
. Passe a propriedade Options
deste objeto para o construtor da sua classe DBContext
.
var mongoClient = new MongoClient("<Your MongoDB Connection URI>");
var dbContextOptions =
new DbContextOptionsBuilder<MyDbContext>().UseMongoDB(mongoClient, "<Database Name");
var db = new MyDbContext(dbContextOptions.Options);
Operações CRUD
Agora vamos ver como codificar as operações CRUD. Vamos focar em cada operação individualmente.
Operação de Criação
Para criar um novo documento no MongoDB, você usa o método Add
no DbSet
e chama SaveChanges
. Este é um exemplo de criação de um novo cliente:
using (var context = new MyDbContext(options))
{
var customer = new Customer { Name = "Beau Carnes", Order = "Laptop" };
context.Customers.Add(customer);
context.SaveChanges();
}
Este código cria uma nova instância de Customer
e a adiciona à coleção Customers
. O método SaveChanges
salva o novo cliente no banco de dados MongoDB.
Leitura de Operação
Para ler documentos da coleção MongoDB, você pode usar consultas LINQ no DbSet
. Este é um exemplo de como recuperar todos os clientes:
using (var context = new MyDbContext(options))
{
var customers = context.Customers.ToList();
foreach (var customer in customers)
{
Console.WriteLine($"Customer: {customer.Name}, Order: {customer.Order}");
}
}
Esse código recupera todos os clientes da coleção Customers
e imprime seus detalhes.
Atualização de Operação
Para atualizar um documento existente, você recupera o documento, modifica suas propriedades e chama SaveChanges
. Este é um exemplo de atualizar uma ordem de cliente:
using (var context = new MyDbContext(options))
{
var customer = context.Customers.FirstOrDefault(c => c.Name == "Beau Carnes");
if (customer != null)
{
customer.Order = "Smartphone";
context.SaveChanges();
}
}
Esse código encontra o cliente chamado “Beau Carnes” e atualiza sua ordem para “Smartphone”.
Exclusão de Operação
Para excluir um documento, você recupera o documento, remove-o do DbSet
e chama SaveChanges
. Este é um exemplo de excluir um cliente:
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();
}
}
Esse código encontra o cliente chamado “Beau Carnes” e remove-o da coleção Customers
.
Rastreamento de Mudança
As capacidades de rastreamento de mudança do EF Core são totalmente suportadas, permitindo atualizações eficientes em documentos. Quando você modifica uma entidade e chama SaveChanges
, o EF Core gerará as comandos MongoDB necessários para atualizar somente os campos alterados.
Usando o provedor MongoDB EF, você pode integrar seamlessmente o modelo flexível de documentos do MongoDB com as capacidades robustas de ORM do EF Core, oferecendo uma ferramenta poderosa para os desenvolvedores .NET construírem aplicações modernas.
Tutorial
Agora vamos juntar tudo isso e criar um sistema de reserva de restaurantes.
Pré-requisitos
Para acompanhar este tutorial, você vai precisar de algumas coisas:
-
.NET 7.0.
-
Conhecimento básico de ASP.NET MVC e C#.
-
Conta grátis do MongoDB Atlas e cluster de grau grátis.
Criar o projeto
O ASP.NET Core é um framework web muito flexível, permitindo que você crie diferentes tipos de aplicativos web que têm pequenas diferenças em termos de UI ou estrutura. Para este tutorial, vamos criar um projeto MVC que fará uso de arquivos estáticos e controladores. Existem outros tipos de interface que você pode usar, como o React, mas o MVC com views .cshtml é o mais comumente utilizado. Para criar o projeto, vamos usar o CLI do .NET:
dotnet new mvc -o RestRes
Como usamos o CLI, embora seja mais fácil, ele só cria o arquivo csproj e não o arquivo de solução, o que nos permite abrir no Visual Studio, então vamos corrigir isso.
cd RestRes
dotnet new sln
dotnet sln .\RestRes.sln add .\RestRes.csproj
Adicionar os pacotes NuGet
Agora que temos o novo projeto criado, vamos adicionar os pacotes NuGet necessários. Usando o Gerenciador de Pacotes NuGet ou usando o comando abaixo do CLI do .NET, adicione o pacote MongoDB MongoDB.EntityFrameworkCore.
dotnet add package MongoDB.EntityFrameworkCore
Criar os modelos
Antes de começarmos a implementar os novos pacotes que acabamos de adicionar, precisamos criar as modelos que representam as entidades que queremos no nosso sistema de reserva de restaurantes, que serão armazenados obviamente em MongoDB Atlas como documentos. Nas seções seguintes, criaremos os seguintes modelos:
-
Restaurante
-
Reserva
-
ConfiguraçõesMongoDB
Restaurante
A primeira coisa que precisamos fazer é criar o nosso modelo de restaurante que representará os restaurantes disponíveis para serem reservados no nosso sistema.
-
Crie um novo arquivo na pasta Models chamada Restaurant.cs.
-
Adicione o seguinte código:
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; }
}
}
O atributo de coleção antes da classe informa ao aplicativo qual coleção do banco de dados estamos usando. Isso nos permite ter nomes ou capitalizações diferentes entre nossa classe e nossa coleção, se quisermos.
Reserva
Também precisamos criar uma classe de reserva para representar qualquer reserva que fizermos no nosso sistema.
-
Crie um novo arquivo na pasta Models chamado Reservation.cs.
-
Adicione o seguinte código a ele:
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; }
}
}
ConfiguraçõesMongoDB
Embora não seja um documento em nossa base de dados, precisamos de uma classe de modelo para armazenar nossas configurações relacionadas ao MongoDB para que elas possam ser usadas em toda a aplicação.
-
Crie outro arquivo em Models chamado MongoDBSettings.cs.
-
Adicione o código a seguir:
namespace RestRes.Models
{
public class MongoDBSettings
{
public string AtlasURI { get; set; }
public string DatabaseName { get; set; }
}
}
Configuração do EF Core
Aqui chegamos à parte interessante. Vamos começar a implementar o EF Core e aproveitar o novo provedor MongoDB. Se você já estiver familiarizado com o EF Core, parte desse processo lhe pode parecer familiar.
RestaurantReservationDbContext
-
Crie uma pasta chamada Services, e crie um arquivo chamado RestaurantReservationDbContext.cs.
-
Substitua o código dentro do namespace pelo seguinte:
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>();
}
}
}
Se você estiver familiarizado com o EF Core, isso pode parecer-lhe familiar. A classe extende o DbContext e criamos propriedades DbSet que armazenam os modelos que também estarão presentes na base de dados. Também sobrepomos o método OnModelCreating. Você pode notar que, ao contrário do uso com o SQL Server, nós não chamamos .ToTable(). Podíamos chamar ToCollection em vez disso, mas isso não é necessário aqui, já que especificamos a coleção usando atributos nas classes.
Adicione a string de conexão e os detalhes do banco de dados à appsettings
Anteriormente, criamos um modelo de MongoDBSettings e agora precisamos adicionar os valores que as propriedades mapeadas para nossa appsettings.
-
Tanto em appsettings.json quanto em appsettings.Development.json, adicione o seguinte novo segmento:
"MongoDBSettings": { "AtlasURI": "mongodb+srv://<username>:<password>@<url>", "DatabaseName": "restaurants" }
-
Substitua a URI Atlas com a sua própria string de conexão do Atlas.
Atualizando o program.cs
Agora que configuramos nossos modelos e o DbContext, é hora de adicioná-los ao arquivo program.cs.
Após a linha existente builder.Services
.AddControllersWithViews();
, adicione o seguinte código:
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 ?? ""));
Criando os serviços
Agora, é hora de adicionar os serviços que usaremos para se comunicar com o banco de dados através do RestaurantBookingDbContext que criamos. Para cada serviço, criaremos uma interface e a classe que a implementa.
IRestaurantService e RestaurantService
A primeira interface e serviço que implementaremos é para executar as operações CRUD na coleção de restaurantes. Este é conhecido como o padrão de repositório. Podem ver pessoas interagindo com o DbContext diretamente. Mas a maioria das pessoas usa este padrão, o que é o motivo para incluí-lo aqui.
-
Se você ainda não fez, crie uma pasta Services para armazenar nossas novas classes.
-
Crie uma interface IRestaurantService e adicione o seguinte código para os métodos que implementaremos:
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);
}
}
-
Crie um arquivo de classe RestaurantService.
-
Atualize a declaração da classe RestaurantService para que ela implemente a interface IRestaurantService que acabamos de criar:
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 e ReservationService
A seguir é a nossa IReservationService e ReservationService.
Crie a interface IReservationService e adicione os seguintes métodos:
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);
}
}
Crie a classe ReservationService e substitua sua classe pelo código seguinte que implementa todos os métodos:
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);
}
}
}
Esse código é muito semelhante ao código para a classe RestaurantService, mas para reservas em vez disso.
Adicionando-os ao Injeção de Dependência
A etapa final para os serviços é adicioná-los ao contêiner de injeção de dependências.
No interior do Program.cs, adicione o seguinte código depois do código que lá adicionei anteriormente:
builder.Services.AddScoped<IRestaurantService, RestaurantService>();
builder.Services.AddScoped<IReservationService, ReservationService>();
Criando os modelos de visual
Antes de implementarmos o front-end, precisamos adicionar os modelos de visual que vão actuar como mensageiro entre nossos fronts e backends, onde necessário. Mesmo que nossa aplicação seja muito simples, implementar o modelo de visual é ainda uma boa prática, já que ajuda a desacoplar as partes do aplicativo.
RestaurantListViewModel
O primeiro que vamos adicionar é o RestaurantListViewModel. Isso será usado como o modelo em nossa página Razor posterior para listar restaurantes em nosso banco de dados.
-
Crie uma nova pasta no root do projeto chamada ViewModels.
-
Adicione um novo arquivo chamado RestaurantListViewModel.cs.
-
Adicione o seguinte código:
using RestRes.Models;
namespace RestRes.ViewModels
{
public class RestaurantListViewModel
{
public IEnumerable<Restaurant>? Restaurants { get; set; }
}
}
RestaurantAddViewModel
Nós também queremos um modelo de visual que possa ser usado pela view Add que adicionaremos depois.
-
Dentro da pasta ViewModels, crie um novo arquivo chamado RestaurantAddViewModel.cs.
-
Add:
using RestRes.Models;
namespace RestRes.ViewModels
{
public class RestaurantAddViewModel
{
public Restaurant? Restaurant { get; set; }
}
}
ReservationListViewModel
Agora, queremos fazer algo muito similar para as reservas, começando com ReservationListViewModel.
-
Crie um novo arquivo na pasta ViewModels chamado ReservationListViewModel.cs.
-
Add:
using RestRes.Models;
namespace RestRes.ViewModels
{
public class ReservationListViewModel
{
public IEnumerable<Reservation>? Reservations { get; set; }
}
}
ReservationAddViewModel
Finalmente, temos o ReservationAddViewModel.
Crie o arquivo e adicione este código:
using RestRes.Models;
namespace RestRes.ViewModels
{
public class ReservationAddViewModel
{
public Reservation? Reservation { get; set; }
}
}
Adding to _ViewImports
Mais tarde, nós vamos adicionar referências aos nossos modelos e viewmodels nas views. Para a aplicação saber o que eles são, precisamos adicionar referências a eles no arquivo _ViewImports.cshtml dentro da pasta Views.
Já haverá algumas referências lá, incluindo TagHelpers, então queremos adicionar referências para nossas pastas .Models e .ViewModels. Portanto, o topo do arquivo deveria parecer com isto:
@using RestRes
@using RestRes.Models
@using RestRes.ViewModels
Creating the controllers
Now that we have the backend implementation and the view models we will refer to, we can start working toward the front end. We will be creating two controllers: one for Restaurant and one for Reservation.
RestaurantController
The first controller we will add is for the restaurant.
-
Dentro da pasta existente Controllers, adicione um novo arquivo de controller chamado RestaurantController.cs. Se estiver usando o Visual Studio, use o modelo de controller MVC – Controller vazio.
-
Adicione este código:
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
Agora para o controller de reserva. Isto é muito semelhante ao RestaurantController, mas tem uma referência a ambos o restaurante e o serviço de reserva, pois precisamos associar um restaurante a uma reserva. Isso é devido ao fato do momento, o provedor EF Core não suporta relações entre entidades, portanto, podemos relacionar entidades de uma maneira diferente.
-
Crie outro arquivo de controller MVC vazio chamado ReservationController.cs.
-
Cole o seguinte código:
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);
}
}
}
Criando as views
Agora que temos o back end e os controladores prontos com os endpoints para o nosso sistema de reserva de restaurantes, é hora de implementar as views. Isso será usando as páginas Razor. Você verá também referências a classes de Bootstrap, pois é a ferramenta de estilo em CSS que vem com as aplicações MVC. Vamos fornecer views para as operações CRUD tanto para listagens quanto para reservas.
Listando restaurantes
Primeiro, fornecerá uma visualização que mapeará para a raiz de /Restaurante, que de acordo com a convenção, olhará para o método Index que implementamos.
ASP.NET Core MVC usa um padrão de convenção onde você nomeia o arquivo .cshtml com o nome do ponto final/método que ele usa e vive dentro de uma pasta chamada pelo nome de seu controlador.
-
Dentro da pasta Views, crie uma nova subpasta chamada Restaurant.
-
Dentro dessa pasta Restaurant, adicione uma nova visualização criando um arquivo chamado
Index.cshtml
. Se você usar as templates disponíveis, você quer Visualização Razor – Vazio. Nomeie a visualização Index. -
Adicione este código:
@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>
Agora vamos atualizar a rota padrão de Home para /Restaurant.
Em Program.cs, dentro de app.MapControllerRoute
, substitua a linha de padrão por:
pattern: "{controller=Restaurant}/{action=Index}/{id?}");
Se executássemos isso agora, os botões levariam a 404s porque ainda não implementamos. Então vamos fazer isso agora.
Adicionando restaurantes
Começaremos com o formulário para adicionar novos restaurantes.
-
Adicione um novo, vazio Visualização Razor dentro da subpasta Restaurant chamada Add.cshtml.
-
Adicione o código a seguir:
@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>
Editando restaurantes
O código da página de edição é quase idêntico à de adição, mas utiliza o restaurante como modelo, já que irá usar o restaurante passado para preencher o formulário de edição.
-
Adicione outra view dentro da subpasta Restaurant chamada Edit.cshtml.
-
Adicione o seguinte código:
@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>
Excluindo restaurantes
A página final que precisamos implementar é a página chamada quando o botão de excluir é clicado.
-
Crie uma nova view vazia chamada Delete.cshtml.
-
Adicione o seguinte código:
@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>
Listando reservas
Já adicionamos as views para os restaurantes, então agora adicionaremos as views para as reservas, começando pela listagem de quaisquer reservas existentes.
-
Crie uma nova pasta chamada Reservation dentro da pasta Views.
-
Crie um novo arquivo de view vazio chamado Index.cshtml.
-
Adicione o seguinte código para exibir as reservas, se existirem:
@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>
}
Adicionando reservas
Adicionando reservas é a próxima coisa.
-
Crie uma view vazia chamada Add.cshtml.
-
Adicione o seguinte código:
@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>
Editando reservas
A próxima coisa é editar reservas.
-
Crie uma view vazia chamada Edit.cshtml.
-
Adicione o seguinte código:
@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>
Excluindo reservas
A próxima coisa é excluir reservas.
-
Crie uma view vazia chamada Delete.cshtml.
-
Adicione o seguinte código:
@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>
Atualizando o NavBar
A coisa final a adicionar é atualizar a barra de navegação do aplicativo para que possamos facilmente alternar entre restaurantes e reservas.
Vá até o arquivo em Views/Shared/_Layout.cshtml
. Encontre o div
com a classe navbar-collapse
. Remova toda essa seção e adicione o seguinte código:
<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>
Testando o nosso aplicativo
Agora temos um aplicativo funcional que usa o novo provedor MongoDB para EF Core. Agora é hora de testá-lo tudo e visitar nossos endpoints para garantir que tudo funciona.
No terminal, execute o seguinte comando:
dotnet run
Tente editar restaurantes e adicionar reservas. Depois, você pode navegar até a página do banco de dados MongoDB Atlas e ver que suas mudanças estão refletidas no banco de dados.
Operações Avançadas do MongoDB: Pesquisa Atlas e Pesquisa Vetorial
O fornecedor EF Core está construído sobre o MongoDB C# Driver. since tem acesso ao o MongoClient quando criando o DbContext, isso permite que execute operações avançadas do MongoDB, como Pesquisa Atlas e Pesquisa Vetorial. essas funcionalidades melhoram as capacidades de sua aplicação, permitindo funcionalidades de pesquisa poderosas enquanto ainda aproveita o família de framework EF Core.
Pesquisa Atlas
A Pesquisa Atlas é um motor de pesquisa de texto completo fornecido pelo MongoDB Atlas. Permite que você execute consultas de pesquisa sofisticadas em seus dados MongoDB. Com a Pesquisa Atlas, você pode implementar recursos como sugestão de palavras-chave, pesquisa por faces e classificação baseada na relevância.
Para usar a Pesquisa Atlas com o provedor EF Core, siga estes passos:
-
Configurar índices no MongoDB Atlas:
-
Vá para o seu cluster MongoDB Atlas.
-
Navegue até a aba “Pesquisa” e crie um novo índice em sua coleção. Defina os campos que você deseja tornar pesquisáveis.
-
-
Defina Campos Pesquisáveis em Seus Modelos: Em seus modelos em C#, certifique-se de que os campos que você deseja pesquisar estejam corretamente definidos. Aqui está um exemplo de definição de um modelo de Produto.
public class Produto { public ObjectId Id { get; set; } public string Nome { get; set; } public string Descrição { get; set; } public decimal Preço { get; set; } public string Categoria { get; set; } }
- Executando Consultas de Pesquisa: Use as capacidades do MongoDB .NET Driver para realizar pesquisas de texto. Como o EF Core em si não suporta diretamente a sintaxe de pesquisa específica do MongoDB, você precisará usar o driver em conjunto c;
Este exemplo mostra como executar uma busca de texto na coleção Products
. O filtro Text
ajuda a procurar através de todos os campos indexados definidos em seu índice de busca do Atlas Search.
Pesquisa Vetorial
A Pesquisa Vetorial no MongoDB é usada para procurar documentos com base em similaridades vetoriais, o que é particularmente útil para aplicações envolvendo aprendizado de máquina, recomendações e processamento de linguagem natural. A Pesquisa Vetorial permite que você execute consultas usando vetores que representam texto, imagens ou outos dados de alta dimensão.
-
Criar e Armazenar Vetores: Primeiro, certifique-se que seus documentos contêm vetores. Você pode precisar de pré-processamento de dados para gerar esses vetores usando modelos de aprendizado de máquina.>
-
Indexar Vetores no MongoDB Atlas: Crie um índice especial no campo vetorial no MongoDB Atlas para permitir buscas de similaridade de vetores eficientes.
-
Realizando Pesquisas Vetoriais: Use o MongoDB .NET Driver para consultar com base na similaridade vetorial.
Integrando com EF Core
Embora o Provedor MongoDB EF Core simplifique as operações CRUD, alguns recursos avançados como Atlas Search e Pesquisa Vetorial exigem o uso direto do MongoDB .NET Driver. No entanto, você ainda pode integrar essas operações dentro do seu aplicativo baseado em EF Core, usando o driver para funcionalidades de busca e o EF Core para outras tarefas de gerenciamento de dados.
Ao combinar EF Core e os recursos avançados do MongoDB, você pode construir aplicativos poderosos e flexíveis que aproveitam o melhor dos dois mundos—padrões de acesso a dados estruturados do EF Core e as poderosas capacidades de busca do MongoDB Atlas.
Source:
https://www.freecodecamp.org/news/using-entity-framework-core-with-mongodb/