Andreani.ARQ.Mongo¶
Overview¶
Se desarrolló la librería Andreani.ARQ.Mongo
para realizar la implementación de MongoDB.Driver .El objetivo es abstraer de las configuraciones a lxs desarrolladorxs y disponibilizar de interfaces comunes para una rápida adopción y uso de las tecnologías.
Info
Andreani.ARQ.Mongo utiliza la librería de MongoDB.Driver como base para las interacciones con la base de datos. ver MongoDB.Driver
Instalación¶
- Instalar en el proyecto
Application
la dependencia conCore.MongoDb
dotnet add package Andreani.Arq.Core.MongoDb
- Instalar en el proyecto
Infreastructure
la dependencia conMongo
dotnet add package Andreani.Arq.Mongo
- Instalar en el proyecto
Infreastructure
la dependencia conObservability.ElasticApm.Mongo
oObservability.OpenTelemetry.Mongo
dotnet add package Andreani.Arq.Observability.ElasticApm.Mongo dotnet add package Andreani.Arq.Observability.OpenTelemetry.Mongo
Configuración¶
Para realizar la configuración debemos, en principio instalar como paquete nuget la librería Andreani.ARQ.Mongo
.
En los archivos de configuración appsettings
debemos disponer de una sección con la configuración de Mongo
{
"MongoRegistry":{
"ConnectionString": "mongodb://localhost:27017",
"DataBase": "NameDb"
}
}
MongoRegistry:
ConnectionString: "mongodb://localhost:27017"
DataBase: "NameDb"
El parámetro ConnectionString
será la connection que tome la libreria.
Para incluir la configuración a nuestro proyecto la siguiente línea al bootstrap de la capa de Infrastructure
public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
{
services.AddMongo(configuration);
return services;
}
El método AddMongo
realiza la configuración y la inyección de dependencias.
Al método AddMongo
se puede configurar con:
public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
{
services.AddMongo(configuration, configSectionName: "MongoRegistry");
return services;
}
configSectionName
: es el nombre de la sección de configuración. Por defecto:MongoRegistry
Healthcheck¶
La librería ya tiene la configuración de healthcheck, se complementa con la configuración de Andreani.ARQ.WebHost
, para acceder a los healthcheck debe ivocar la ruta: http://*:*/health
o http://*:*/healthcheck
para obtener más info.
Interfaces Disponibles¶
En la nueva versión de la librería Mongo implementa 2 interfaces, una Generica IMongoRepository<Entity>
, y otra común IMongoRepository
, la gran diferencia es que la Interface Generica se va utilizar para el manejo de una entidad especifica ( la misma cuenta con las operaciones básicas de lectura y escritura)
IMongoRepository Generic
public interface IMongoRepository<Entity>
{
List<Entity> GetAll();
Task<List<Entity>> GetAllAsync();
Entity GetOne(FilterDefinition<Entity> expression);
Task<Entity> GetOneAsync(FilterDefinition<Entity> expression);
List<Entity> Where(Expression<Func<Entity, bool>> expression = null, int skip = 0, int take = 0);
List<Entity> Where(FilterDefinition<Entity> filter, int skip = 0, int take = 0);
Task<List<Entity>> WhereAsync(Expression<Func<Entity, bool>> expression = null, int skip = 0, int take = 0);
Task<List<Entity>> WhereAsync(FilterDefinition<Entity> filter, int skip = 0, int take = 0);
void Insert(Entity entity);
Task InsertAsync(Entity entity);
void InsertRange(List<Entity> entities);
Task InsertRangeAsync(List<Entity> entities);
void Update(FilterDefinition<Entity> filter, UpdateDefinition<Entity> expression);
void Update(Entity entity, FilterDefinition<Entity> expression);
Task UpdateAsync(Entity entity, FilterDefinition<Entity> expression);
Task UpdateAsync(FilterDefinition<Entity> filter, UpdateDefinition<Entity> expression);
void UpdateRange(List<Entity> entities, FilterDefinition<Entity> expression);
Task UpdateRangeAsync(List<Entity> entities, FilterDefinition<Entity> expression);
void UpdateMany(FilterDefinition<Entity> filter, UpdateDefinition<Entity> expression);
Task UpdateManyAsync(FilterDefinition<Entity> filter, UpdateDefinition<Entity> expression);
void Delete(FilterDefinition<Entity> expression);
Task DeleteAsync(FilterDefinition<Entity> expression);
void DeleteRange(FilterDefinition<Entity> expression);
Task DeleteRangeAsync(FilterDefinition<Entity> expression);
}
, mientras que la Interface común se va a utilizar para manejo avanzado de la base y va a contar con los siguientes métodos:
IMongoRepository Común
public interface IMongoRepository
{
void UseDatabase(Action<IMongoDatabase> action);
TResponse UseDatabase<TResponse>(Func<IMongoDatabase, TResponse> action);
Task UseDatabaseAsync(Func<IMongoDatabase, Task> action);
Task<TResponse> UseDatabaseAsync<TResponse>(Func<IMongoDatabase, Task<TResponse>> action);
TResponse UseCollection<TDocument, TResponse>(string name, Func<IMongoCollection<TDocument>, TResponse> action);
TDocument UseCollection<TDocument>(string name, Func<IMongoCollection<TDocument>, TDocument> action);
void UseCollection<TDocument>(string name, Action<IMongoCollection<TDocument>> action);
Task<TDocument> UseCollectionAsync<TDocument>(string name, Func<IMongoCollection<TDocument>, Task<TDocument>> action);
Task<TResponse> UseCollectionAsync<TDocument, TResponse>(string name, Func<IMongoCollection<TDocument>, Task<TResponse>> action);
Task UseCollectionAsync<TDocument>(string name, Func<IMongoCollection<TDocument>, Task> action);
void CreateCollection(string id);
}
Tip
Ya no es obligatorio heredar de `MongoEntity` para poder usar la librería, y ahora recibe el tipo de dato que deseamos que sea muestro Id (`MongoEntity<PK>`).
Ya no existe el metodo `SetDocumentName` y por eso se creó el Attribute `CollectionName` en caso de que la collection tenga un nombre diferente al de la clase y se utiliza así:
[CollectionName("Person")]
public class Person : MongoEntity<string>
{
public string Nombre { get; set; }
public string Apellido { get; set; }
}
IMongoRepository Generic¶
GetOne¶
GetOneAsync(FilterDefinition
var filter = Builders<Person>.Filter.Eq(x => x.Id, request.Id);
var person = await _repository.GetOneAsync(filter);
Update¶
UpdateAsync(Entity entity, FilterDefinition
public async Task<Response<string>> Handle(UpdatePersonCommand request, CancellationToken cancellationToken)
{
var filter = Builders<Person>.Filter.Eq(x => x.Id, request.Id);
var person = await _repository.GetOneAsync(filter);
var response = new Response<string>();
if (person is null)
{
response.AddNotification("#3123", nameof(request.Id), string.Format(ErrorMessage.NOT_FOUND_RECORD, "Person", request.Id));
response.StatusCode = System.Net.HttpStatusCode.NotFound;
return response;
}
person.Nombre = request.Nombre;
person.Apellido = request.Apellido;
await _repository.UpdateAsync(person, filter);
return response;
}
UpdateAsync(FilterDefinition
public async Task<Response<string>> Handle(UpdatePersonCommand request, CancellationToken cancellationToken)
{
var filter = Builders<Person>.Filter.Eq(x => x.Id, request.Id);
var person = await _repository.GetOneAsync(filter);
var response = new Response<string>();
if (person is null)
{
response.AddNotification("#3123", nameof(request.Id), string.Format(ErrorMessage.NOT_FOUND_RECORD, "Person", request.Id));
response.StatusCode = System.Net.HttpStatusCode.NotFound;
return response;
}
var update= Builders < Person >.Update
.Set(x => x.Nombre, request.Nombre)
.Set(x=> x.Apellido,request.Apellido);
await _repository.UpdateAsync(filter, update);
return response;
}
Tip
El `UpdateMany` es parecido al `UpdateAsync(FilterDefinition<Entity> filter, UpdateDefinition<Entity> expression)` pero este actualiza a todas las entidades que encuentre con el filtro y le setea los datos que definimos en el `UpdateDefinition`.
Where¶
Where(FilterDefinition
var filter = Builders<MyEntity>.Filter.Eq("name", "architecture-it");
var listArchitecture = _repository.Where(filter);
Where(Expression
var documentMailArchitecture = _repository.Where(p => p.User.Mail.Equals("architecture-it@andreani.com"));
IMongoRepository Común¶
UseCollection¶
UseCollection es una función que inyecta la Collection, esta pensado para utilizarse en caso de necesitar actualizar un modelo complejo o utilizar las funciones del MongoDb.Driver que no estan disponibles desde la librería.
var filter = Builders<MyEntity>.Filter.Eq("name", "architecture-it")
var documentArchitecture = await _repository.UseCollectionAsync<MyEntity>("nameCollection",async con => {
return await con.Find(filter).FirstOrDefaultAsync();
});
var filter = Builders<long>.Filter.Eq("name", "architecture-it");
var totalDocumentNameArchitecture = _repository.UseCollection<long>("nameCollection", con => {
return con.CountDocuments(filter);
});