Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Learn why MongoDB was selected as a leader in the 2024 Gartner® Magic Quadrant™
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Idiomaschevron-right
C#chevron-right

Consulte seus dados com o ASP.NET Core, o OData e o provedor do MongoDB Entity Framework Core

Markus Wildgruber7 min read • Published May 31, 2024 • Updated Jul 08, 2024
C#
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Entre as boas notícias do MongoDB.local NYC '24, estava o anúncio de que o MongoDB Entity Framework Core Provider ficara disponível globalmente. O fornecedor se integra ao Entity Framework e habilita desenvolvedores .NET a acessar facilmente dados em bancos de dados MongoDB com um framework bem conhecido.
Esta publicação mostra como você pode configurar o provedor em um projeto C# e criar uma API com o ASP.NET Core que oferece um ponto de extremidade compatível com OData. Para quem é novo no OData, esse é um protocolo usado para criar APIs REST consultáveis. As interfaces de usuário podem acessar essas APIs e usá-las para fornecer visualizações tabulares que oferecem um conjunto avançado de interações com o usuário, como filtragem, classificação ou paginação. Como o OData é um padrão aberto, há uma grande variedade de ferramentas que podem acessar endpoints compatíveis com OData, por exemplo, Microsoft Excel ou Microsoft Power BI.
Se você quiser acompanhar as amostras nesta publicação, criamos um endpoint que consulta os filmes no sample_flix-database. A maneira mais fácil de obter uma instância deste banco de dados de exemplo é carregar os dados de exemplo em um cluster MongoDB Atlas. Se você ainda não tiver um cluster, poderá configurar um cluster gratuito do MongoDB Atlas M0 (consulte este link para obter um guia).
Embora esta publicação use um projeto recém-criado de API Web do ASP.NET Core, é perfeitamente possível adicionar OData para oferecer os endpoints além dos endpoints REST existentes. Ao criar um novo projeto, talvez você queira ativar o suporte OpenAPI para ter uma maneira fácil de testar a API mais tarde. Além disso, o novo projeto deve usar controladores em vez de uma API mínima.
Assistente de informações adicionais mostrando valores padrão

Criar o Entity Framework DbContext

Após configurar o projeto ASP.NET Core, primeiro definiremos o Entity Framework DbContext e, em seguida, o configuraremos com o MongoDB Entity Framework Core Provider.
A primeira etapa é adicionar o pacote MongoDB Entity Framework Core Provider ao projeto por meio da UI ou da CLIdotnet :
1dotnet add package MongoDB.EntityFrameworkCore
Em seguida, definimos a classe de entidade que contém as propriedades que queremos ler do banco de dados:
1// requires using MongoDB.Bson;
2public class Movie
3{
4 public string Id { get; set; } = ObjectId.GenerateNewId().ToString();
5 public string Title { get; set; } = string.Empty;
6 public string? Plot { get; set; }
7 public IEnumerable<string>? Genres { get; set; }
8 public IEnumerable<string>? Cast { get; set; }
9 // additional properties as required
10}
Algumas das propriedades (por exemploPlot) são tipos de referência anuláveis. Isso afirma que valores ausentes no banco de dados não resultam em erro ao ler os documentos.
A próxima etapa é definir o DbContext e adicionar a configuração para a entidade. Isso inclui vincular a entidade a uma coleção e, como estamos trabalhando com documentos existentes que seguem uma convenção de nomenclatura diferente, mapear os nomes de propriedade do documento para os do .NET POCO:
1// requires using Microsoft.EntityFrameworkCore;
2// requires using MongoDB.Bson;
3// requires using MongoDB.EntityFrameworkCore.Extensions;
4
5public class MflixDbContext : DbContext
6{
7 public MflixDbContext(DbContextOptions options)
8 : base(options)
9 {
10 }
11
12 public DbSet<Movie> Movies { get; init; }
13
14 protected override void OnModelCreating(ModelBuilder modelBuilder)
15 {
16 base.OnModelCreating(modelBuilder);
17 var movieEntity = modelBuilder.Entity<Movie>();
18 movieEntity.ToCollection("movies");
19 movieEntity.Property(x => x.Id)
20 .HasElementName("_id")
21 .HasConversion<ObjectId>();
22 movieEntity.Property(x => x.Title).HasElementName("title");
23 movieEntity.Property(x => x.Plot).HasElementName("plot");
24 movieEntity.Property(x => x.Genres).HasElementName("genres");
25 movieEntity.Property(x => x.Cast).HasElementName("cast");
26 }
27}
A propriedadeId requer atenção especial: no documento MongoDB, a propriedade_id é armazenada como um ObjectId. Em uma interface OData, usar strings em vez de um ObjectId como valor do identificador é muito mais fácil. Ao adicionar conversão de valor, podemos ter o melhor dos dois mundos: ObjectIds no MongoDB e strings no .NET.
Para finalizar a configuração do MongoDB Entity Framework Core Provider, registramos o cliente, o banco de dados e oMflixDbContext no container IoC:
1// requires using Microsoft.EntityFrameworkCore;
2// requires using MongoDB.Driver;
3// requires using MongoDBEFODataVerify;
4
5builder.Services.AddSingleton<IMongoClient>(prov =>
6{
7 // Retrieve connection string from configuration
8 return new MongoClient("<your MongoDB connection string>");
9});
10builder.Services.AddSingleton(prov =>
11{
12 var client = prov.GetRequiredService<IMongoClient>();
13 // Retrieve database name from configuration
14 return client.GetDatabase("sample_mflix");
15});
16builder.Services.AddDbContext<MflixDbContext>((prov, options) =>
17{
18 var database = prov.GetRequiredService<IMongoDatabase>();
19 options.UseMongoDB(
20 database.Client,
21 database.DatabaseNamespace.DatabaseName);
22});
Se você estiver usando apenas o Entity Framework, será suficiente registrar MflixDbContext e criar o cliente no método factory. O código de exemplo acima registra o cliente e a instância do banco de dados separadamente para que você possa injetá-los independentemente, se necessário.
Com a configuraçãoDbContext, também poderíamos usar o scaffolding do controlador para gerar o código para os controladores REST, se necessário. No entanto, para o propósito desta postagem, criaremos um endpoint OData do zero.

Adicione o OData ao projeto

A primeira etapa ao adicionar OData a um projeto é fazer referência ao pacoteMicrosoft.AspNetCore.OData, por meio da interface do usuário ou usando a CLIdotnet :
1dotnet add package Microsoft.AspNetCore.OData
Em seguida, adicionamos um método que define o modelo EDM para a interface OData em Program.cs:
1// requires using Microsoft.OData.Edm;
2// requires using Microsoft.OData.ModelBuilder;
3
4IEdmModel GetEdmModel()
5{
6 var model = new ODataConventionModelBuilder();
7 model.EnableLowerCamelCase();
8 model.EntitySet<Movie>("Movies");
9 return model.GetEdmModel();
10}
EnableLowerCamelCase altera a convenção de nomenclatura das propriedades para começar com um caractere minúsculo. Isso corresponde ao comportamento da serialização JSON em uma REST API padrão.
Em seguida, registramos os componentes do OData no contêiner IoC adicionando o seguinte código em Program.cs:
1// requires using Microsoft.OData;
2
3// This should be already in the code
4builder.Services
5 .AddControllers()
6// This is new
7 .AddOData(options => options
8 .Select()
9 .Filter()
10 .OrderBy()
11 .Count()
12 .SetMaxTop(100)
13 .AddRouteComponents("odata", GetEdmModel()));
O código acima permite várias operações do OData e restringe o número máximo de entidades que um cliente pode solicitar para evitar um conjunto de resultados muito grande.
Por último, adicionamos um controlador que fornece o ponto de extremidade OData para nossa query. O nome do controlador deve ser MoviesController para corresponder ao registro da entidade definida em GetEdmModel:
1// requires using Microsoft.AspNetCore.OData.Query;
2// requires using Microsoft.AspNetCore.OData.Routing.Controllers;
3
4public class MoviesController : ODataController
5{
6 private readonly MflixDbContext _dbContext;
7
8 public MoviesController(MflixDbContext dbContext)
9 {
10 _dbContext = dbContext;
11 }
12
13 [EnableQuery(
14 PageSize = 1000,
15 AllowedOrderByProperties = "title, plot")]
16 public IQueryable<Movie> Get()
17 {
18 return _dbContext.Movies;
19 }
20}
Injetamos uma instância de MflixDbContext no controlador para recuperar os filmes e marcar o métodoGetcom o atributoEnableQuery. A propriedadePageSize nos permite definir o número máximo de resultados enviados ao cliente. O uso deAllowedOrderByProperties restringe as propriedades que podem ser usadas em operações de classificação.
O nome deve corresponder ao nome serializado - camel case minúsculas em nossa amostra, conforme chamamos EnableLowerCamelCase em GetEdmModel anteriormente. Existem várias outras opções que você pode usar para ajustar o comportamento do endpoint de query. Consulte a documentação do ASP.NET Core OData para obter detalhes.

Teste o endpoint

Agora estamos prontos para testar o endpoint OData e iniciá-lo no depurador. Se você habilitou o OpenAPI e o Swagger UI em seu projeto, você pode usar o Swagger UI para um teste simples. Isto é suficiente para verificar a prontidão básica do endpoint e serve como um bom ponto de partida.
Para solicitações mais sofisticadas, insira a URL do OData em um navegador ou use uma ferramenta como o Postman ou curl com URLs do OData.
Uma solicitação simples para https://localhost:\<YOUR PORT\>/odata/Movies deve retornar 10 filmes no seguinte formato:
1{
2 "@odata.context": "https://localhost:7104/odata/$metadata#Movies",
3 "value": [
4 {
5 "id": "573a1390f29313caabcd4135",
6 "title": "Blacksmith Scene",
7 "plot": "Three men hammer on an anvil...",
8 "genres": [
9 "Short"
10 ],
11 "cast": [
12 "Charles Kayser",
13 "John Ott"
14 ]
15 },
16 // 999 more results
17 ],
18 "@odata.nextLink": "https://localhost:7104/odata/Movies?$skip=10"
19}
Para usar os recursos do OData, como paginação e filtragem, você também pode tentar as seguintes solicitações:
  • Filtrar por título:
    https://localhost:\<YOUR PORT\>/odata/Movies?$filter=title eq 'The Godfather'
  • Filtrar por parte do título - não diferencia maiúsculas de minúsculas: https://localhost:\<YOUR PORT\>/odata/Movies?$filter=contains(tolower(title), 'godfather')
  • Paginação com $skip, $top e $count:
    https://localhost:\<YOUR PORT\>/odata/Movies?$count=true&$top=10&$skip=10
  • Classificando com $orderBy:
    https://localhost:\<YOUR PORT\>/odata/Movies?$orderBy=title ASC

OData usando o Driver MongoDB C#

E se você já tiver uma API e estiver usando o driver MongoDB C# sem Entity Framework? Puro e simples, tudo que você precisa para que o OData funcione é um IQueryable<T>.
Isso pode ser fornecido facilmente por IMongoCollection<T>.AsQueryable() para que também possamos criar o endpoint OData dessa forma:
1// requires using Microsoft.AspNetCore.OData.Query;
2// requires using Microsoft.AspNetCore.OData.Routing.Controllers;
3// requires using MongoDB.Driver;
4
5public class MoviesController : ODataController
6{
7 private readonly IMongoCollection<Movie> _collMovies;
8
9 public MoviesController(IMongoDatabase db)
10 {
11 _collMovies = db.GetCollection<Movie>("movies");
12 }
13
14 [EnableQuery(
15 PageSize = 1000,
16 AllowedOrderByProperties = "title, plot")]
17 public IQueryable<Movie> Get()
18 {
19 return _collMovies.AsQueryable();
20 }
21}
Observe que você também precisa configurar o mapeamento para a classeMovie adicionando atributos ou definindo o mapa de classes obrigatóriamente.

Opções avançadas de query

Até agora, criamos um ponto de extremidade OData que oferece suporte a opções básicas para filtragem, classificação e paginação com o pacote Microsoft.AspNetCore.OData. Infelizmente, este pacote não suporta $select e $expand em suas solicitações. Se você quiser dar um passo além e também adicionar suporte para essas operações, precisará confiar em um pacote fornecido pelo MongoDB e fazer referência aMongoDB.AspNetCore.OData em vez do pacote da Microsoft. Tudo que você precisa fazer é substituir EnableQuery por MongoEnableQuery e seu endpoint suportará essas operações.
1// requires using Microsoft.AspNetCore.OData.Routing.Controllers;
2// requires using MongoDB.AspNetCore.OData.Query;
3// requires using MongoDB.Driver;
4
5public class MoviesController : ODataController
6{
7 private readonly IMongoCollection<Movie> _collMovies;
8
9 public MoviesController(IMongoDatabase db)
10 {
11 _collMovies = db.GetCollection<Movie>("movies");
12 }
13
14 // Change this from EnableQuery to MongoEnableQuery
15 [MongoEnableQuery(
16 PageSize = 1000,
17 AllowedOrderByProperties = "title, plot")]
18 public IQueryable<Movie> Get()
19 {
20 return _collMovies.AsQueryable();
21 }
22}
No momento da redação deste artigo, você precisa seguir a abordagem descrita na seção OData usando o driver C# do MongoDB acima e não pode usar um DbSet<T> fornecido pelo MongoDB Entity Framework Core Provider.
Para obter detalhes sobre o pacote, consulte este repositório no Github.

Resumo

Nesta publicação, mostramos como é fácil adicionar opções de query avançadas à sua API, com um endpoint OData que se baseia no Entity Framework e no MongoDB. Essa API pode ser usada para fornecer opções de query avançadas na interface do usuário de seus aplicativos ou pode ser acessada a partir de ferramentas populares como o Microsoft Excel. Como ambas as estruturas são muito poderosas e oferecem muitas opções, não deixe de conferir a documentação no MongoDB Entity Framework Core Provider e ASP.NET Core OData.
Você já usa o OData ou o MongoDB Entity Framework Core Provider? Informe - nos nos fóruns.
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.
Iniciar a conversa

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Tutorial

Fundamentos do pipeline de agregação do MongoDB C#


Oct 11, 2024 | 5 min read
Tutorial

Introdução ao Unity para criar um jogo 2D


Apr 02, 2024 | 9 min read
Tutorial

Manipulação de aggregation pipelines complexas com c# C#


Nov 15, 2024 | 5 min read
Tutorial

Integrar o Azure Key Vault com a criptografia em nível de campo no lado do cliente do MongoDB


May 24, 2022 | 9 min read
Sumário