Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern.Abstractions
1.2.9
dotnet add package Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern.Abstractions --version 1.2.9
NuGet\Install-Package Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern.Abstractions -Version 1.2.9
<PackageReference Include="Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern.Abstractions" Version="1.2.9" />
<PackageVersion Include="Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern.Abstractions" Version="1.2.9" />
<PackageReference Include="Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern.Abstractions" />
paket add Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern.Abstractions --version 1.2.9
#r "nuget: Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern.Abstractions, 1.2.9"
#addin nuget:?package=Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern.Abstractions&version=1.2.9
#tool nuget:?package=Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern.Abstractions&version=1.2.9
Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern.Abstractions
Biblioteca de abstracciones para implementar el patrón Repository con SQL Server en aplicaciones .NET. Define una interfaz genérica que facilita las operaciones CRUD y consultas complejas para entidades de dominio.
Instalación
Package Manager
Install-Package Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern.Abstractions
.NET CLI
dotnet add package Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern.Abstractions
Características principales
- Patrón Repository genérico: Define una interfaz
IRepo<TEntity>
para operaciones de base de datos - Operaciones CRUD completas: Métodos para crear, leer, actualizar y eliminar entidades
- Mapeo de entidades: Soporte para mapeo automático y personalizado de resultados de consultas
- Consultas con DTO: Funciones para obtener resultados como DTOs personalizados
- Soporte para múltiples tipos: Permite mapear consultas con múltiples tipos de entidades (hasta 7 tipos)
- Flexibilidad en procedimientos almacenados: Permite especificar nombres de SP personalizados
- Control de parámetros: Manejo avanzado de parámetros dinámicos para consultas
- Soporte para esquemas: Permite organizar procedimientos por esquemas de base de datos
- Configuración de tiempos de espera: Control fino de timeouts para operaciones de larga duración
- Soporte para SQL directo: Además de procedimientos almacenados, permite ejecutar SQL directo
Interfaz principal
La biblioteca define la interfaz genérica IRepo<TEntity>
que sirve como base para implementar el patrón Repository:
public interface IRepo<TEntity> where TEntity : class
{
ISqlDataAccess db { get; }
string PrefixSp { get; }
// Métodos básicos para obtener entidades
Task<IEnumerable<TEntity>> Get(object? Param = null, bool RemoveUnused = true, Enum? connId = null, int? Timeout = null, string? Sp = null, CommandType CmdType = CommandType.StoredProcedure);
Task<TEntity?> GetById(object? id = null, Enum? connId = null, int? Timeout = null, string? Sp = null, CommandType CmdType = CommandType.StoredProcedure);
Task<TEntity?> GetBy(string Sp, object? Param = null, bool RemoveUnused = true, Enum? connId = null, int? Timeout = null, CommandType CmdType = CommandType.StoredProcedure);
// Métodos para operaciones CUD (Create, Update, Delete)
Task<DBEntity> Save(object? Param = null, bool RemoveUnused = true, Enum? connId = null, int? Timeout = null, string? Sp = null, CommandType CmdType = CommandType.StoredProcedure);
Task<DBLastInsertEntity<TId>> SaveAndGetId<TId>(object? Param = null, bool RemoveUnused = true, Enum? connId = null, int? Timeout = null, string? Sp = null, CommandType CmdType = CommandType.StoredProcedure);
Task<DBEntity> Delete(object? Param = null, bool RemoveUnused = true, Enum? connId = null, int? Timeout = null, string? Sp = null, CommandType CmdType = CommandType.StoredProcedure);
Task<DBEntity> DeleteById(object? id = null, string? StartPrefix = null, string? EndPrefix = null, Enum? connId = null, int? Timeout = null, string? Sp = null, CommandType CmdType = CommandType.StoredProcedure);
Task<DBEntity> DeleteByIds(object? id = null, string? StartPrefix = null, string? EndPrefix = null, Enum? connId = null, int? Timeout = null, string? Sp = null, CommandType CmdType = CommandType.StoredProcedure);
// Métodos para obtener DTOs
Task<IEnumerable<TDto>> GetDto<TDto>(object? Param = null, bool RemoveUnused = true, Enum? connId = null, int? Timeout = null, string? Sp = null, CommandType CmdType = CommandType.StoredProcedure);
Task<Dto?> GetDtoById<Dto>(object? id = null, Enum? connId = null, int? Timeout = null, string? Sp = null, CommandType CmdType = CommandType.StoredProcedure);
Task<Dto?> GetDtoBy<Dto>(string Sp, object? Param = null, bool RemoveUnused = true, Enum? connId = null, int? Timeout = null, CommandType CmdType = CommandType.StoredProcedure);
// Métodos para combos (select/dropdown)
Task<IEnumerable<SelectItemDto>> GetCbo(object? Param = null, bool RemoveUnused = true, Enum? connId = null, int? Timeout = null, string? Sp = null, CommandType CmdType = CommandType.StoredProcedure);
Task<IEnumerable<ReactSelectItemDto>> GetRCbo(object? Param = null, bool RemoveUnused = true, Enum? connId = null, int? Timeout = null, string? Sp = null, CommandType CmdType = CommandType.StoredProcedure);
// Métodos para mapeo manual
Task<IEnumerable<TEntity>> MapGet<T2>(Func<TEntity, T2, TEntity> mapeo, string spliOn, object? Param = null, bool RemoveUnused = true, Enum? connId = null, int? Timeout = null, string? Sp = null, CommandType CmdType = CommandType.StoredProcedure);
Task<TEntity?> MapGetById<T2>(Func<TEntity, T2, TEntity> mapeo, string spliOn, object? id = null, Enum? connId = null, int? Timeout = null, string? Sp = null, CommandType CmdType = CommandType.StoredProcedure);
Task<TEntity?> MapGetBy<T2>(string Sp, Func<TEntity, T2, TEntity> mapeo, string spliOn, object? Param = null, bool RemoveUnused = true, Enum? connId = null, int? Timeout = null, CommandType CmdType = CommandType.StoredProcedure);
// Y múltiples sobrecargas adicionales para mapeo con hasta 7 tipos...
// Utilidad para manejar parámetros dinámicos
DynamicParameters? UseParamerter(object? parameters);
}
Uso de las abstracciones
Este paquete contiene solo las interfaces y no las implementaciones. La implementación correspondiente se realiza a través del paquete complementario Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern
.
Registro en el contenedor de IoC
Utilizando los métodos de extensión proporcionados por el paquete de implementación:
// En Program.cs o Startup.cs
var builder = WebApplication.CreateBuilder(args);
// Registrar los servicios necesarios
builder.Services.AddSqlDataAccess(options => {
options.ConnectionString = builder.Configuration.GetConnectionString("Default");
});
// Opción 1: Registrar automáticamente todos los repositorios en un assembly
builder.Services.AddReposFromAssembly(Assembly.GetExecutingAssembly());
// Opción 2: Registrar repositorios específicos manualmente
builder.Services.AddScoped<IRepo<ProductoEntity>, Repo<ProductoEntity>>();
builder.Services.AddScoped<IRepo<ClienteEntity>, Repo<ClienteEntity>>();
Uso en servicios
Una vez registrados, puedes inyectar los repositorios directamente en tus servicios:
public class ProductoService
{
private readonly IRepo<ProductoEntity> _productoRepo;
public ProductoService(IRepo<ProductoEntity> productoRepo)
{
_productoRepo = productoRepo;
}
public async Task<IEnumerable<ProductoDto>> ObtenerProductosActivos()
{
return await _productoRepo.GetDto<ProductoDto>(
new { Activo = true }
);
}
public async Task<DBEntity> GuardarProducto(ProductoEntity producto)
{
return await _productoRepo.Save(producto);
}
}
Patrones de uso común
Operaciones CRUD básicas
// Obtener todos los registros
var productos = await _productoRepo.Get();
// Obtener por ID
var producto = await _productoRepo.GetById(new { Id = 123 });
// Obtener con condición específica
var productoActivo = await _productoRepo.GetBy("GetByCodigo", new { Codigo = "P001" });
// Guardar (insertar o actualizar)
var result = await _productoRepo.Save(productoEntity);
// Guardar y obtener el ID generado
var insertResult = await _productoRepo.SaveAndGetId<int>(nuevoProducto);
int nuevoId = insertResult.LastInsertId;
// Eliminar
var result = await _productoRepo.Delete(new { Id = 123 });
// Eliminar por ID
var result = await _productoRepo.DeleteById(123);
// Eliminar múltiples registros
var result = await _productoRepo.DeleteByIds(new[] { 1, 2, 3 });
Trabajar con DTOs
// Obtener como DTO
var productosDto = await _productoRepo.GetDto<ProductoDto>();
// Obtener DTO por ID
var productoDto = await _productoRepo.GetDtoById<ProductoDto>(123);
// Obtener DTO con condición específica
var productosRecientes = await _productoRepo.GetDtoBy<ProductoDto>("GetRecent", new { Days = 30 });
Trabajar con procedimientos almacenados y SQL directo
// Usando procedimiento almacenado (comportamiento por defecto)
var resultado = await _productoRepo.Get(
new { Activo = true },
Sp: "ObtenerProductosActivos"
);
// Usando SQL directo
var resultadoSql = await _productoRepo.Get(
new { Activo = true },
Sp: "SELECT * FROM Productos WHERE Activo = @Activo",
CmdType: CommandType.Text
);
// Especificar timeout para operaciones largas
var reporteComplejo = await _productoRepo.GetDto<ReporteDto>(
Param: new { FechaInicio = fechaInicio, FechaFin = fechaFin },
Timeout: 120, // 120 segundos
Sp: "GenerarReporteVentas"
);
Mapeo de múltiples entidades
// Obtener entidad principal con entidades relacionadas mapeadas automáticamente
var productoConDetalles = await _productoRepo.GetById<DetalleEntity, ProveedorEntity>(
"Id,DetalleId,ProveedorId", // Campos para hacer split
new { Id = 123 }
);
// Mapeo personalizado con una entidad relacionada
var productosMapeados = await _productoRepo.MapGet<CategoriaEntity>(
(producto, categoria) => {
producto.NombreCategoria = categoria.Nombre;
return producto;
},
"CategoriaId",
new { Activo = true }
);
// Mapeo personalizado con múltiples entidades relacionadas
var ventasCompletas = await _productoRepo.MapGet<ClienteEntity, VendedorEntity, ProductoEntity>(
(venta, cliente, vendedor, producto) => {
venta.NombreCliente = cliente.Nombre;
venta.NombreVendedor = vendedor.Nombre;
venta.NombreProducto = producto.Nombre;
return venta;
},
"ClienteId,VendedorId,ProductoId",
new { Fecha = DateTime.Today }
);
Obteniendo datos para combos/dropdowns
// Para select estándar (obtiene objetos Value/Text)
var opcionesSelect = await _categoriaRepo.GetCbo();
// Para React Select (obtiene objetos value/label)
var opcionesReactSelect = await _categoriaRepo.GetRCbo();
Uso de parámetros de salida
// Usando parámetros de salida
var param = new DynamicParameters();
param.Add("Id", 123);
var producto = await _productoRepo.GetById(
dp => {
var totalVentas = dp.Get<decimal>("TotalVentas");
Console.WriteLine($"Total de ventas: {totalVentas}");
},
id: 123,
SqlParameter: param
);
Convenciones para procedimientos almacenados
La interfaz asume ciertas convenciones para nombres de procedimientos almacenados:
- {Esquema}.{Entidad}Get: Para listar entidades
- {Esquema}.{Entidad}GetById: Para obtener una entidad por ID
- {Esquema}.{Entidad}Save: Para crear o actualizar entidades
- {Esquema}.{Entidad}Delete: Para eliminar entidades
- {Esquema}.{Entidad}GetCbo: Para obtener datos formateados para combos
- {Esquema}.{Entidad}GetRCbo: Para obtener datos formateados para React Select
Donde:
- {Esquema}: Es el esquema de la base de datos (por defecto "dbo")
- {Entidad}: Es el nombre de la entidad (derivado automáticamente del tipo genérico TEntity)
Estas convenciones pueden modificarse mediante el parámetro Sp
en cada método.
Integración con otros paquetes Nosabit
Este paquete de abstracciones está diseñado para trabajar con otros paquetes de la familia Nosabit:
- Nosabit.Core: Proporciona tipos como
DBEntity
y extensiones de utilidad - Nosabit.Adapters.Persistence.SqlServer.Abstractions: Define la interfaz
ISqlDataAccess
utilizada por el repositorio - Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern: Implementación concreta con métodos de extensión para el registro de dependencias
Beneficios de utilizar estas abstracciones
- Separación de responsabilidades: Desacopla la lógica de acceso a datos de la lógica de negocio
- Código DRY: Evita repetir código para operaciones comunes en cada repositorio
- Flexibilidad: Proporciona múltiples sobrecargas para adaptarse a diferentes escenarios
- Testabilidad: Facilita la creación de mocks para pruebas unitarias
- Mantenibilidad: Permite cambiar la implementación sin afectar a los consumidores
- Control granular: Permite especificar tiempos de espera, tipos de comando y conexiones específicas
- Soporte para SQL directo: No limita al uso de procedimientos almacenados, también permite SQL directo
Requisitos
- .NET 6.0 o superior
- Dapper 2.1.66 o superior
Licencia
Este proyecto está licenciado bajo la Licencia MIT.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. |
-
net9.0
- Dapper (>= 2.1.66)
- Nosabit.Adapters.Persistence.SqlServer.Abstractions (>= 1.2.5)
- Nosabit.Core (>= 1.2.3)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern.Abstractions:
Package | Downloads |
---|---|
Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.