Overview
Mongo DB es una base de datos NoSQL que se ha vuelto muy popular en los últimos años, debido a su flexibilidad y escalabilidad. En este documento se describe cómo usar la librería CodeDesignPlus.Net.Mongo para interactuar con una base de datos de Mongo DB.
Propósito y alcance
CodeDesignPlus.Net.Mongo
es una biblioteca diseñada para facilitar la integración de MongoDB con aplicaciones .NET Core. Su propósito es simplificar el acceso y la manipulación de datos en MongoDB, proporcionando una capa de abstracción que permite a los desarrolladores centrarse en la lógica de negocio en lugar de en los detalles de la implementación de la base de datos. La biblioteca incluye utilidades comunes, patrones y abstracciones que promueven una arquitectura limpia y mantenible.
Principales características
- Operaciones Asíncronas: Soporte completo para operaciones asíncronas, mejorando el rendimiento y la capacidad de respuesta de las aplicaciones.
- Proyección y Filtrado Avanzado: Facilita capacidades avanzadas de proyección y filtrado, permitiendo consultas eficientes y específicas.
- Integración Sencilla: Se integra perfectamente con otras bibliotecas de CodeDesignPlus.Net, proporcionando una experiencia de desarrollo coherente y unificada.
- Escalabilidad: Diseñada para manejar operaciones de base de datos escalables, adecuada para aplicaciones de gran tamaño y alto rendimiento.
- Documentación Completa: Incluye documentación extensa y soporte para tareas comunes de MongoDB, facilitando el aprendizaje y la implementación.
Casos de uso típicos
- Aplicaciones Web: Integración de MongoDB en aplicaciones web ASP.NET Core para gestionar datos de usuarios, contenido dinámico, y más.
- Microservicios: Uso en arquitecturas de microservicios donde se requiere una base de datos NoSQL escalable y de alto rendimiento.
- Aplicaciones en Tiempo Real: Implementación en aplicaciones que requieren procesamiento y almacenamiento de datos en tiempo real, como sistemas de mensajería o seguimiento en vivo.
- Sistemas de Gestión de Contenidos (CMS): Utilización en CMS para almacenar y gestionar grandes volúmenes de contenido de manera eficiente.
- Aplicaciones de Análisis de Datos: Uso en aplicaciones que requieren análisis y procesamiento de grandes conjuntos de datos, aprovechando las capacidades de agregación y filtrado de MongoDB.
Componentes Principales
RepositoryBase
: Clase base que proporciona métodos comunes para interactuar con una colección de MongoDB.OperationBase
: Clase base que define operaciones comunes como Crear, Leer, Actualizar y Eliminar (CRUD) en MongoDB.MongoOptions
: Clase que define las opciones de configuración para la conexión a MongoDB.
Directorysrc
DirectoryCodeDesignPlus.Net.Mongo
DirectoryConverter
- ExpressionConverter.cs
DirectoryExceptions
- MongoException.cs
DirectoryExtensions
- ServiceCollectionExtensions.cs
DirectoryOperations
- OperationBase.cs
DirectoryRepository
- RepositoryBase.cs
DirectoryCodeDesignPlus.Net.Mongo.Abstractions
- IRepositoryBase.cs
DirectoryOperations
- ICreateOperation.cs
- IDeleteOperation.cs
- IOperationBase.cs
- IUpdateOperation.cs
DirectoryOptions
- MongoOptions.cs
Primeros Pasos
En esta sección, aprenderás a instalar y configurar la librería CodeDesignPlus.Net.Mongo
en tu proyecto de .NET. Además, explorarás los servicios, métodos de extensión y excepciones que proporciona la librería para interactuar con bases de datos utilizando MongoDB.
Requisitos previos
- .NET 8 o superior.
- Conocimientos básicos de MongoDB y operaciones CRUD.
Instalación
Para instalar la librería CodeDesignPlus.Net.Mongo
, puedes utilizar el administrador de paquetes NuGet o la CLI de .NET. A continución, se muestra un ejemplo de cómo instalar la librería utilizando la CLI de .NET:
dotnet add package CodeDesignPlus.Net.Mongo
Install-Package CodeDesignPlus.Net.Mongo
<PackageReference Include="CodeDesignPlus.Net.Mongo" Version="1.0.0" />
Configuración básica
-
Asignar las opciones de configuración en el
appsettings.json
:{"Core": {"Business": "CodeDesignPlus","AppName": "sample-mongo-repositorybase","Version": "v1","Description": "Sample of CodeDesignPlus.Net.Core","Contact": {"Name": "CodeDesignPlus","Email": "custom@outlook.com"}},"Mongo": {"Enable": true,"ConnectionString": "mongodb://localhost:27017","Database": "db_sample","RegisterAutomaticRepositories": true}} -
Registrar los servicios en el contenedor de dependencias:
//...serviceCollection.AddMongo<Startup>(configuration);
Ejemplo rápido
En este ejemplo CodeDesignPlus.Net.Mongo.Sample, se muestra cómo utilizar la librería CodeDesignPlus.Net.Mongo
para realizar operaciones CRUD en una colección de MongoDB.
// See https://aka.ms/new-console-template for more informationusing CodeDesignPlus.Net.Core.Abstractions.Models.Criteria;using CodeDesignPlus.Net.Mongo.Extensions;using CodeDesignPlus.Net.Mongo.Sample.RepositoryBase;using CodeDesignPlus.Net.Mongo.Sample.RepositoryBase.DTOs;using CodeDesignPlus.Net.Mongo.Sample.RepositoryBase.Entities;using CodeDesignPlus.Net.Mongo.Sample.RepositoryBase.Respositories;using Microsoft.Extensions.Configuration;using Microsoft.Extensions.DependencyInjection;using MongoDB.Driver;
var configuration = new ConfigurationBuilder() .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .Build();
var serviceCollection = new ServiceCollection();
serviceCollection.AddLogging();serviceCollection.AddMongo<Startup>(configuration);
var serviceProvider = serviceCollection.BuildServiceProvider();
var repository = serviceProvider.GetRequiredService<IUserRepository>();
var product = new ProductEntity{ Id = Guid.NewGuid(), Name = "Product 1", CreatedAt = SystemClock.Instance.GetCurrentInstant(), CreatedBy = Guid.NewGuid(), IsActive = true};
var tenant = Guid.NewGuid();var createdBy = Guid.NewGuid();
var user = UserAggregate.Create(Guid.NewGuid(), "John Doe", "john.doe@codedesignplus.com", tenant, createdBy);
user.AddProduct(product);
var users = new List<UserAggregate>{ UserAggregate.Create(Guid.NewGuid(), "Jane Doe", "jane.doe@codedesignplus.com", tenant, createdBy), UserAggregate.Create(Guid.NewGuid(), "John Smith", "john.smith@codedesignplus.com", tenant, createdBy)};
// Create a new userawait repository.CreateAsync(user, CancellationToken.None);
// Create some usersawait repository.CreateRangeAsync(users, CancellationToken.None);
// Change stateawait repository.ChangeStateAsync<UserAggregate>(user.Id, false, tenant, CancellationToken.None);
// Find a uservar userFound = await repository.FindAsync<UserAggregate>(user.Id, tenant, CancellationToken.None);
// Criteris to find usersvar criteria = new Criteria{ Filters = "IsActive=true"};
var usersFound = await repository.MatchingAsync<UserAggregate>(criteria, tenant, CancellationToken.None);
// Criteria with projectionvar projection = await repository.MatchingAsync<UserAggregate, UserDto>(criteria, x => new UserDto{ Id = x.Id, Name = x.Name, Email = x.Email}, tenant, CancellationToken.None);
// Criteria at subdocument level and projectionvar projectionSubdocument = await repository.MatchingAsync<UserAggregate, ProductEntity>(user.Id, criteria, x => x.Products, tenant, CancellationToken.None);
// Update uservar userUpdate = await repository.FindAsync<UserAggregate>(user.Id, tenant, CancellationToken.None);
userUpdate.UpdateName("John Doe Updated");
await repository.UpdateAsync(userUpdate, CancellationToken.None);
// Update some usersvar usersUpdate = await repository.MatchingAsync<UserAggregate>(criteria, tenant, CancellationToken.None);
usersUpdate.ForEach(x => x.UpdateName($"{x.Name} Updated"));
await repository.UpdateRangeAsync(usersUpdate, CancellationToken.None);
// Transactionawait repository.TransactionAsync(async (database, session) =>{ var userTransaction = UserAggregate.Create(Guid.NewGuid(), "John Doe Transaction", "john.doe@codedesignplus.com", tenant, createdBy);
var collection = database.GetCollection<UserAggregate>(typeof(UserAggregate).Name);
await collection.InsertOneAsync(session, userTransaction, cancellationToken: CancellationToken.None);
}, CancellationToken.None);
// Delete uservar filterUser = Builders<UserAggregate>.Filter.Eq(x => x.Id, user.Id);
await repository.DeleteAsync(filterUser, tenant, CancellationToken.None);
// Delete some usersawait repository.DeleteRangeAsync(users, tenant, CancellationToken.None);
-
Configuración de Mongo en
appsettings.json
:{"Core": {"Business": "CodeDesignPlus","AppName": "sample-mongo-repositorybase","Version": "v1","Description": "Sample of CodeDesignPlus.Net.Core","Contact": {"Name": "CodeDesignPlus","Email": "custom@outlook.com"}},"Mongo": {"Enable": true,"ConnectionString": "mongodb://localhost:27017","Database": "db_sample","RegisterAutomaticRepositories": true}} -
Creamos las entidades:
Procedemos a crear las entidades que representarán los documentos en la colección de MongoDB, estas entidades deben implementar la interfaz
IEntity
deCodeDesignPlus.Net.Core.Abstractions
.using System;using CodeDesignPlus.Net.Core.Abstractions;namespace CodeDesignPlus.Net.Mongo.Sample.RepositoryBase.Entities;public class ProductEntity : IEntity{public Guid Id { get; set; }public bool IsActive { get; set; }public Instant CreatedAt { get; set; }public Guid CreatedBy { get; set; }public Instant? UpdatedAt { get; set; }public Guid? UpdatedBy { get; set; }public required string Name { get; set; }public string? Description { get; set; }}using CodeDesignPlus.Net.Core.Abstractions;namespace CodeDesignPlus.Net.Mongo.Sample.RepositoryBase.Entities;public class UserAggregate(Guid id) : AggregateRoot(id){public string Name { get; private set; } = string.Empty;public string Email { get; private set; } = string.Empty;public List<ProductEntity> Products { get; private set; } = [];private UserAggregate(Guid id, string name, string email, Guid tenant, Guid createdBy): this(id){Name = name;Email = email;Tenant = tenant;IsActive = true;CreatedBy = createdBy;CreatedAt = SystemClock.Instance.GetCurrentInstant();}public static UserAggregate Create(Guid id, string name, string email, Guid tenant, Guid createdBy){return new UserAggregate(id, name, email, tenant, createdBy);}public void AddProduct(ProductEntity product){Products.Add(product);}public void UpdateName(string name){Name = name;}} -
Creamos el repositorio:
Para efectos de este ejemplo, procederemos a crear el repositorio
UserRepository
que hereda deRepositoryBase
.using CodeDesignPlus.Net.Mongo.Abstractions.Options;using CodeDesignPlus.Net.Mongo.Sample.RepositoryBase.Entities;using Microsoft.Extensions.Logging;using Microsoft.Extensions.Options;namespace CodeDesignPlus.Net.Mongo.Sample.RepositoryBase.Respositories;public class UserRepository(IServiceProvider serviceProvider, IOptions<MongoOptions> mongoOptions, ILogger<UserRepository> logger): CodeDesignPlus.Net.Mongo.Repository.RepositoryBase(serviceProvider, mongoOptions, logger), IUserRepository{public Task CustomMethodAsync(){var collection = this.GetCollection<UserAggregate>();// Do something with the collectionreturn Task.CompletedTask;}} -
Creamos la clase Startup:
Al utilizar el SDK de CodeDesignPlus, generalmente es necesario crear una clase
Startup
que implemente la interfazIStartup
. Esto facilita una mejor organización de los servicios que se desean registrar en el contenedor de dependencias de la aplicación, para cada una de las capas del servicio.using System;using CodeDesignPlus.Net.Core.Abstractions;using Microsoft.Extensions.Configuration;using Microsoft.Extensions.DependencyInjection;namespace CodeDesignPlus.Net.Mongo.Sample.RepositoryBase;public class Startup : IStartup{public void Initialize(IServiceCollection services, IConfiguration configuration){}} -
Registramos los servicios en el contenedor de dependencias:
serviceCollection.AddMongo<Startup>(configuration); -
Obtenemos la instancia de nuestro repositorio:
var repository = serviceProvider.GetRequiredService<IUserRepository>(); -
Creamos un nuevo usuario:
var user = new UserEntity{Id = Guid.NewGuid(),Name = "John Doe",Email = "john.doe@codedesignplus.com",CreatedAt = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),CreatedBy = Guid.NewGuid(),IsActive = true};await repository.CreateAsync(user, CancellationToken.None);
using CodeDesignPlus.Net.Mongo.Extensions;using CodeDesignPlus.Net.Mongo.Sample.OperationBase;using CodeDesignPlus.Net.Mongo.Sample.OperationBase.Entities;using CodeDesignPlus.Net.Mongo.Sample.OperationBase.Respositories;using CodeDesignPlus.Net.Mongo.Sample.OperationBase.Services;using CodeDesignPlus.Net.Security.Abstractions;using Microsoft.Extensions.Configuration;using Microsoft.Extensions.DependencyInjection;
var configuration = new ConfigurationBuilder() .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .Build();
var serviceCollection = new ServiceCollection();
serviceCollection.AddLogging();serviceCollection.AddMongo<Startup>(configuration);serviceCollection.AddSingleton<IUserContext, FakeUserContext>();
var serviceProvider = serviceCollection.BuildServiceProvider();
var repository = serviceProvider.GetRequiredService<IUserRepository>();
var tenant = Guid.NewGuid();var createdBy = Guid.NewGuid();
var user = UserAggregate.Create(Guid.NewGuid(), "John Doe", "john.doe@codedesignplus.com", tenant, createdBy);
// Create a new userawait repository.CreateAsync(user, CancellationToken.None);
// Find a user to updateuser.UpdateName("John Doe Updated");
await repository.UpdateAsync(user.Id, user, tenant, CancellationToken.None);
// Delete a userawait repository.DeleteAsync(user.Id, tenant, CancellationToken.None);
-
Configuración de Mongo en
appsettings.json
:{"Core": {"Business": "CodeDesignPlus","AppName": "sample-mongo-operationbase","Version": "v1","Description": "Sample of CodeDesignPlus.Net.Core","Contact": {"Name": "CodeDesignPlus","Email": "custom@outlook.com"}},"Mongo": {"Enable": true,"ConnectionString": "mongodb://localhost:27017","Database": "db_sample","RegisterAutomaticRepositories": true}} -
Creamos la entidad para el ejemplo:
Procedemos a crear la entidad que representará los documentos en la colección de MongoDB, esta entidad debe implementar la interfaz
IEntity
deCodeDesignPlus.Net.Core.Abstractions
.using System;using CodeDesignPlus.Net.Core.Abstractions;namespace CodeDesignPlus.Net.Mongo.Sample.OperationBase.Entities;public class ProductEntity : IEntity{public Guid Id { get; set; }public bool IsActive { get; set; }public Instant CreatedAt { get; set; }public Guid CreatedBy { get; set; }public Instant? UpdatedAt { get; set; }public Guid? UpdatedBy { get; set; }public required string Name { get; set; }public string? Description { get; set; }}using CodeDesignPlus.Net.Core.Abstractions;namespace CodeDesignPlus.Net.Mongo.Sample.OperationBase.Entities;public class UserAggregate(Guid id) : AggregateRoot(id){public string Name { get; private set; } = string.Empty;public string Email { get; private set; } = string.Empty;public List<ProductEntity> Products { get; private set; } = [];private UserAggregate(Guid id, string name, string email, Guid tenant, Guid createdBy): this(id){Name = name;Email = email;Tenant = tenant;IsActive = true;CreatedBy = createdBy;CreatedAt = SystemClock.Instance.GetCurrentInstant();}public static UserAggregate Create(Guid id, string name, string email, Guid tenant, Guid createdBy){return new UserAggregate(id, name, email, tenant, createdBy);}public void AddProduct(ProductEntity product){Products.Add(product);}public void UpdateName(string name){Name = name;}} -
Creamos el repositorio:
Para efectos de este ejemplo, procederemos a crear el repositorio
UserRepository
que hereda deOperationBase
.using CodeDesignPlus.Net.Mongo.Abstractions.Options;using CodeDesignPlus.Net.Mongo.Repository;using CodeDesignPlus.Net.Mongo.Sample.OperationBase.Entities;using CodeDesignPlus.Net.Security.Abstractions;using Microsoft.Extensions.Logging;using Microsoft.Extensions.Options;namespace CodeDesignPlus.Net.Mongo.Sample.OperationBase.Respositories;public class UserRepository(IUserContext authenticatetUser, IServiceProvider serviceProvider, IOptions<MongoOptions> mongoOptions, ILogger<UserRepository> logger): CodeDesignPlus.Net.Mongo.Operations.OperationBase<UserAggregate>(authenticatetUser, serviceProvider, mongoOptions, logger), IUserRepository{} -
Creamos la clase Startup:
Al utilizar el SDK de CodeDesignPlus, generalmente es necesario crear una clase
Startup
que implemente la interfazIStartup
. Esto facilita una mejor organización de los servicios que se desean registrar en el contenedor de dependencias de la aplicación, para cada una de las capas del servicio.using System;using CodeDesignPlus.Net.Core.Abstractions;using Microsoft.Extensions.Configuration;using Microsoft.Extensions.DependencyInjection;namespace CodeDesignPlus.Net.Mongo.Sample.OperationBase;public class Startup : IStartup{public void Initialize(IServiceCollection services, IConfiguration configuration){}} -
Creamos el servicio de usuario:
Para efectos de este ejemplo, procederemos a crear el servicio
FakeUserContext
que implementaIUserContext
. Este servicio se utiliza para obtener información del usuario autenticado. Para un uso en producción se debe usar la implementación que provee la libreriaCodeDesignPlus.Net.Security
.using System;using System.Security.Claims;using CodeDesignPlus.Net.Security.Abstractions;namespace CodeDesignPlus.Net.Mongo.Sample.OperationBase.Services;public class FakeUserContext : IUserContext{public bool IsApplication => false;public Guid IdUser => Guid.Parse("1f4eac7b-4b3b-4b3b-8b3b-4b3b4b3b4b3b");public bool IsAuthenticated => true;public string Name => "John Doe";public string FirstName => "John";public string LastName => "Doe";public string City => "Bogotá";public string Country => "Colombia";public string PostalCode => "110111";public string StreetAddress => "Calle 123 # 123 - 123";public string State => "Cundinamarca";public string JobTitle => "Software Developer";public string[] Emails => ["john.doe@codedesignplus.com"];public Guid Tenant => Guid.Parse("2f4eac7b-4b3b-4b3b-8b3b-4b3b4b3b4b3b");public ClaimsPrincipal User => new();public TValue GetClaim<TValue>(string claimType){throw new NotImplementedException();}public TValue GetHeader<TValue>(string header){throw new NotImplementedException();}} -
Registramos los servicios en el contenedor de dependencias:
serviceCollection.AddMongo<Startup>(configuration);serviceCollection.AddSingleton<IUserContext, FakeUserContext>(); -
Obtenemos la instancia de nuestro repositorio:
var repository = serviceProvider.GetRequiredService<IUserRepository>(); -
Creamos un nuevo usuario:
var user = new UserEntity{Id = Guid.NewGuid(),Name = "John Doe",Email = "john.doe@codedesignplus.com",//CreatedAt = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), //Valor asignado por la clase OperationBase//CreatedBy = Guid.NewGuid(), //Valor asignado por la clase OperationBaseIsActive = true};await repository.CreateAsync(user, CancellationToken.None);
Métodos de extensión
La librería CodeDesignPlus.Net.Mongo
proporciona una serie de métodos de extensión que facilitan la interacción con MongoDB. A continuación, se muestran algunos de los métodos de extensión más comunes:
ServiceCollectionExtensions
ServiceCollection es una clase que proporciona métodos de extensión para registrar servicios en el contenedor de dependencias de .NET Core.
Opciones de configuración
La librería CodeDesignPlus.Net.Mongo
utiliza la clase MongoOptions
para definir las opciones de configuración necesarias para la conexión a MongoDB. A continuación, se muestran las opciones de configuración disponibles:
Servicios
La librería CodeDesignPlus.Net.Mongo
proporciona una serie de servicios que facilitan la interacción con MongoDB. A continuación, se muestran los servicios disponibles:
RepositoryBase
RepositoryBase
es una clase base que proporciona métodos comunes para interactuar con una colección de MongoDB.
OperationBase
OperationBase
es una clase base que define operaciones comunes como Crear, Leer, Actualizar y Eliminar (CRUD) en MongoDB.
Conclusiones
En este documento, se ha presentado una visión general de la librería CodeDesignPlus.Net.Mongo
y sus principales características. Se ha descrito su propósito, alcance, características, casos de uso típicos y componentes principales. Además, se han proporcionado instrucciones detalladas sobre cómo instalar, configurar y utilizar la librería en un proyecto de .NET Core.