Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern 1.2.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern --version 1.2.1
                    
NuGet\Install-Package Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern -Version 1.2.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern" Version="1.2.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern" Version="1.2.1" />
                    
Directory.Packages.props
<PackageReference Include="Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern --version 1.2.1
                    
#r "nuget: Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern, 1.2.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#addin nuget:?package=Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern&version=1.2.1
                    
Install Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern as a Cake Addin
#tool nuget:?package=Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern&version=1.2.1
                    
Install Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern as a Cake Tool

Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern

Implementación robusta del patrón Repository para SQL Server en aplicaciones .NET basada en Dapper. Este paquete proporciona una implementación concreta de las interfaces definidas en Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern.Abstractions.

NuGet License: MIT

Instalación

Package Manager

Install-Package Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern

.NET CLI

dotnet add package Nosabit.Adapters.Persistence.SqlServer.RepositoryPattern

Características principales

  • Implementación completa del patrón Repository: Implementa la interfaz IRepo<TEntity> para proporcionar acceso a datos
  • Basado en Dapper: Utiliza Dapper para un acceso a datos de alto rendimiento
  • Operaciones CRUD: Implementación completa de operaciones Crear, Leer, Actualizar y Eliminar
  • Mapeo automático y manual: Soporte para mapeo automático de Dapper y mapeo personalizado
  • Operaciones con DTO: Implementación de métodos para trabajar directamente con DTOs
  • Convenciones de nomenclatura: Uso inteligente de nombres para procedimientos almacenados
  • Filtrado de parámetros: Elimina automáticamente parámetros no válidos para evitar errores
  • Registro automático basado en atributos: Escaneo de assemblies para registrar repositorios automáticamente
  • Soporte para múltiples esquemas: Permite organizar procedimientos por esquemas de base de datos

Implementación principal

Este paquete proporciona la clase Repo<TEntity> que implementa la interfaz IRepo<TEntity> definida en el paquete de abstracciones:

public class Repo<TEntity> : IRepo<TEntity> where TEntity : class
{
    private readonly ISqlDataAccess sql;
    private readonly string schema;
    private readonly string Prefix_SP;
    private readonly string TableName;
    public readonly ISqlDataAccess db;
    
    public Repo(ISqlDataAccess sql)
    {
        this.sql = sql;
        this.db = sql;
        TableName = typeof(TEntity).Name.Replace("Entity", "").Replace("Dto", "");
        var schemaAttr = typeof(TEntity).GetCustomAttribute<RepoSchemaAttribute>();

        if (schemaAttr != null && !string.IsNullOrEmpty(schemaAttr.Shema))
        {
            schema = schemaAttr.Shema;
        }
        else
        {
            schema = "dbo"; // Esquema predeterminado
        }
        schema += ".";
        Prefix_SP = schema + TableName;
    }
    
    // Implementación de todos los métodos definidos en IRepo<TEntity>
    // ...
}

Registro en el contenedor de IoC

El paquete proporciona métodos de extensión para facilitar el registro de las implementaciones en contenedores de IoC, incluyendo un método para registro automático basado en atributos:

public static class RepoDependecyInjection
{
    // Registra automáticamente todos los repositorios en un assembly basado en atributos
    public static IServiceCollection AddReposFromAssembly(this IServiceCollection Service, Assembly assembly)
    {
        var entityTypes = assembly.GetTypes()
            .Where(type => type.GetCustomAttribute<RepoAttribute>()!=null)
            .ToList();
        entityTypes.ForEachEnumerable(entityType =>
        {
            var schemaAttr = entityType.GetCustomAttribute<RepoAttribute>()!;
            var repoType = typeof(IRepo<>).MakeGenericType(entityType);
            var repoImplType = typeof(Repo<>).MakeGenericType(entityType);
            if (schemaAttr.RepoTypeDependecy == TypeDependecyInjection.Singleton)
            {
                Service.AddSingleton(repoType, repoImplType);
            }
            else if (schemaAttr.RepoTypeDependecy == TypeDependecyInjection.Scoped)
            {
                Service.AddScoped(entityType, repoImplType);
            }
            else
            {
                Service.AddTransient(entityType, repoImplType);
            }
        });
        return Service;
    }
}

Configuración y uso

1. Definir entidades con atributos

// Define el esquema de base de datos y el tipo de registro para inyección de dependencias
[Repo(RepoTypeDependecy = TypeDependecyInjection.Scoped)]
[RepoSchema("dbo")]
public class ProductoEntity
{
    public int Id { get; set; }
    public string Nombre { get; set; }
    public decimal Precio { get; set; }
    public bool Activo { get; set; }
}

2. Registrar repositorios en Program.cs

var builder = WebApplication.CreateBuilder(args);

// Registrar los servicios necesarios
builder.Services.AddSqlDataAccess(options => {
    options.ConnectionString = "tu_cadena_de_conexion";
});

// 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>>();

var app = builder.Build();
// Resto de la configuración...

3. Uso en 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.ObtenerDto<ProductoDto>(
            new { Activo = true }
        );
    }
    
    public async Task<DBEntity> GuardarProducto(ProductoEntity producto)
    {
        return await _productoRepo.Guardar(producto);
    }
}

Convenciones de nomenclatura

La implementación utiliza convenciones para construir los nombres de los procedimientos almacenados:

  • La clase Repo determina el nombre de tabla a partir del nombre de la entidad, quitando los sufijos "Entity" o "Dto"
  • Utiliza el esquema proporcionado como prefijo
  • Agrega el nombre del método como sufijo

Por ejemplo, para una entidad ProductoEntity en el esquema Inventario:

  • Inventario.ProductoObtener
  • Inventario.ProductoObtenerById
  • Inventario.ProductoGuardar
  • Inventario.ProductoEliminar

Filtrado de parámetros

La implementación incluye un método UseParamerter que filtra automáticamente los parámetros no válidos antes de enviarlos a la base de datos:

public DynamicParameters? UseParamerter(object? parameters)
{
    var useparam = new DynamicParameters();
    
    if (parameters == null) return useparam;
    
    static bool IsNotValidType(Type type) =>
        (type.IsClass && type != typeof(string))
        || type.IsArray
        || (type.IsGenericType &&
            type.GetGenericTypeDefinition() != typeof(Nullable<>));
    
    parameters.GetType().GetProperties()
        .Where(p => p.CanRead && !IsNotValidType(p.PropertyType))
        .ForEachEnumerable(property =>
        {
            var v = property.GetValue(parameters);
            if (v != null) useparam.Add(property.Name, v);
        });
    
    return useparam;
}

Esto evita errores comunes como intentar pasar objetos complejos directamente a Dapper.

Ejemplos de uso

Operaciones CRUD básicas

// Obtener todos los registros
var productos = await _productoRepo.Obtener();

// Obtener por ID
var producto = await _productoRepo.ObtenerById(new { Id = 123 });

// Guardar (insertar o actualizar)
var result = await _productoRepo.Guardar(productoEntity);

// Eliminar
var result = await _productoRepo.Eliminar(new { Id = 123 });

Trabajar con DTOs

// Obtener como DTO
var productosDto = await _productoRepo.ObtenerDto<ProductoDto>();

// Obtener DTO por ID
var productoDto = await _productoRepo.ObtenerDtoById<ProductoDto>(new { Id = 123 });

Obtener múltiples resultados y mapearlos

// Obtener productos con sus categorías usando mapeo automático
var productosConCategorias = await _productoRepo.Obtener<CategoriaEntity>(
    "CategoriaId", 
    new { Activo = true }
);

// Mapeo personalizado con múltiples entidades
var ventasDetalladas = await _productoRepo.MapObtener<ClienteEntity, VendedorEntity>(
    (venta, cliente, vendedor) => {
        venta.NombreCliente = cliente.Nombre;
        venta.NombreVendedor = vendedor.Nombre;
        return venta;
    },
    "Id",
    new { Fecha = DateTime.Today }
);

Trabajar con procedimientos almacenados específicos

// Especificar nombre de procedimiento almacenado
var resultado = await _productoRepo.Obtener(
    new { Activo = true },
    Sp: "ObtenerProductosActivos"
);

Uso de parámetros de salida

// Usando parámetros de salida
var param = new DynamicParameters();
param.Add("Id", 123);

var producto = await _productoRepo.ObtenerById(
    dp => {
        var totalVentas = dp.Get<decimal>("TotalVentas");
        Console.WriteLine($"Total de ventas: {totalVentas}");
    },
    Param: new { Id = 123 },
    SqlParameter: param
);

Dependencias

  • 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.Abstractions: Define la interfaz IRepo<TEntity>
  • Dapper: ORM de alto rendimiento para acceso a datos

Requisitos

  • .NET 6.0 o superior
  • SQL Server 2016 o superior

Licencia

Este proyecto está licenciado bajo la Licencia MIT.

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.2.9 145 4/1/2025
1.2.8 455 3/24/2025
1.2.6 317 3/24/2025
1.2.5 147 3/23/2025
1.2.3 147 3/23/2025
1.2.2 138 3/23/2025
1.2.1 139 3/23/2025
1.2.0 139 3/23/2025
1.0.3 143 3/22/2025
1.0.1 64 3/22/2025
1.0.0 62 3/22/2025