Nosabit.Adapters.Persistence.ICacheHybrid
1.2.1
dotnet add package Nosabit.Adapters.Persistence.ICacheHybrid --version 1.2.1
NuGet\Install-Package Nosabit.Adapters.Persistence.ICacheHybrid -Version 1.2.1
<PackageReference Include="Nosabit.Adapters.Persistence.ICacheHybrid" Version="1.2.1" />
<PackageVersion Include="Nosabit.Adapters.Persistence.ICacheHybrid" Version="1.2.1" />
<PackageReference Include="Nosabit.Adapters.Persistence.ICacheHybrid" />
paket add Nosabit.Adapters.Persistence.ICacheHybrid --version 1.2.1
#r "nuget: Nosabit.Adapters.Persistence.ICacheHybrid, 1.2.1"
#addin nuget:?package=Nosabit.Adapters.Persistence.ICacheHybrid&version=1.2.1
#tool nuget:?package=Nosabit.Adapters.Persistence.ICacheHybrid&version=1.2.1
Nosabit.Adapters.Persistence.ICacheHybrid
Implementación eficiente de caché híbrido para aplicaciones .NET que integra Microsoft.Extensions.Caching.Hybrid, proporcionando un sistema de almacenamiento en caché combinado (memoria y distribuido) con control granular de la invalidación y soporte para claves compuestas.
Instalación
Package Manager
Install-Package Nosabit.Adapters.Persistence.ICacheHybrid
.NET CLI
dotnet add package Nosabit.Adapters.Persistence.ICacheHybrid
PackageReference
<PackageReference Include="Nosabit.Adapters.Persistence.ICacheHybrid" Version="1.1.0" />
Características principales
- Implementación completa de ICacheHybrid: Proporciona la implementación de las interfaces definidas en Nosabit.Adapters.Persistence.ICacheHybrid.Abstractions
- Basado en Microsoft.Extensions.Caching.Hybrid: Utiliza el potente sistema de caché híbrido de Microsoft
- Gestión inteligente de claves: Mantiene un registro de todas las claves de caché para facilitar la invalidación
- Agrupación automática por contexto: Organiza automáticamente las claves de caché por tipo de servicio
- Control de expiración flexible: Permite personalizar la duración de cada entrada de caché
- Invalidación selectiva: Proporciona métodos para invalidar grupos específicos de caché
- Integración con ASP.NET Core: Fácil configuración mediante métodos de extensión
- Alto rendimiento: Optimizado para operaciones de caché frecuentes
Componentes principales
NvCacheHybrid
Implementación principal que interactúa directamente con el HybridCache de Microsoft:
public class NvCacheHybrid : INvCacheHybrid
{
// Almacena un registro de todas las claves de caché para facilitar la invalidación
private ConcurrentDictionary<string, ConcurrentBag<string>> KeysCache =
new ConcurrentDictionary<string, ConcurrentBag<string>>();
// Construye claves únicas y las registra para su seguimiento
private string GetKeys(string mainKey, dynamic?[] keys);
// Implementación de los métodos de obtención y gestión de caché
public ValueTask<T> GetOrCreateAsync<T>(string GroupKey, Func<Task<T>> factory, dynamic?[] deps);
public ValueTask<T> GetOrCreateAsync<T>(string GroupKey, Func<Task<T>> factory, dynamic?[] deps, TimeSpan duration);
public Task Remove(string key);
public Task Remove(string[] keys);
public Task RemoveAll();
}
NvCacheHybridAdapter
Adaptador genérico que implementa la interfaz ICacheHybrid<T>:
public class NvCacheHybridAdapter<TClass> : ICacheHybrid<TClass>
{
// El nombre del tipo se usa como clave principal para agrupar entradas de caché
private readonly string MainKey = typeof(TClass).Name;
// Implementación de los métodos definidos en la interfaz
public ValueTask<T> GetOrCreateAsync<T>(Func<Task<T>> factory, dynamic?[] deps);
public ValueTask<T> GetOrCreateAsync<T>(Func<Task<T>> factory, dynamic?[] deps, TimeSpan duration);
public Task RemoveCache();
public Task RemoveCache(Enum ands);
public Task RemoveCache(params Enum[] ands);
public Task RemoveCacheAll();
}
ICacheHybridContainerDI
Extensiones para la configuración del servicio:
public static class ICacheHybridContainerDI
{
// Configura los servicios necesarios para el sistema de caché híbrido
public static WebApplicationBuilder AddICacheHybridContainerDI(
this WebApplicationBuilder builder,
int Expiration = 5);
}
Configuración
Agrega el sistema de caché híbrido a tu aplicación ASP.NET Core:
// En Program.cs
var builder = WebApplication.CreateBuilder(args);
// Añadir el servicio de caché híbrido con la expiración predeterminada (5 minutos)
builder.AddICacheHybridContainerDI();
// O especificar un tiempo de expiración personalizado (en minutos)
builder.AddICacheHybridContainerDI(Expiration: 10);
var app = builder.Build();
// Resto de la configuración...
Ejemplos de uso
Servicio básico con caché
public class ProductoService
{
private readonly ISqlDataAccess _db;
private readonly ICacheHybrid<ProductoService> _cache;
public ProductoService(ISqlDataAccess db, ICacheHybrid<ProductoService> cache)
{
_db = db;
_cache = cache;
}
// Método que utiliza el caché para datos raramente cambiantes
public async Task<IEnumerable<Producto>> ObtenerTodosAsync()
{
return await _cache.GetOrCreateAsync(
() => _db.QueryAsync<Producto>("sp_ObtenerProductos"),
[nameof(ObtenerTodosAsync)]
);
}
// Método con clave compuesta para caché de elementos individuales
public async Task<Producto> ObtenerPorIdAsync(int id)
{
return await _cache.GetOrCreateAsync(
() => _db.QueryFirstAsync<Producto>("sp_ObtenerProductoPorId", new { Id = id }),
[nameof(ObtenerPorIdAsync), id]
);
}
// Método con duración de caché personalizada para datos volátiles
public async Task<IEnumerable<Producto>> ObtenerDestacadosAsync()
{
return await _cache.GetOrCreateAsync(
() => _db.QueryAsync<Producto>("sp_ObtenerProductosDestacados"),
[nameof(ObtenerDestacadosAsync)],
TimeSpan.FromMinutes(2) // Caché de corta duración
);
}
}
Invalidación granular con enumeraciones
public class VentaService
{
private readonly ISqlDataAccess _db;
private readonly ICacheHybrid<ProductoService> _productoCache;
// Enum para categorizar diferentes tipos de caché
public enum ProductoCacheTipo
{
Listado,
Detalle,
Destacados,
Stock
}
public VentaService(
ISqlDataAccess db,
ICacheHybrid<ProductoService> productoCache)
{
_db = db;
_productoCache = productoCache;
}
// Método que invalida tipos específicos de caché
public async Task<DBEntity> RegistrarVentaAsync(Venta venta)
{
var result = await _db.ExecuteAsync("sp_RegistrarVenta", venta);
// Invalidar solo las cachés de stock y destacados
await _productoCache.RemoveCache(
ProductoCacheTipo.Stock,
ProductoCacheTipo.Destacados
);
return result;
}
// Método que invalida toda la caché de un servicio
public async Task<DBEntity> ActualizarCatalogoAsync()
{
var result = await _db.ExecuteAsync("sp_ActualizarCatalogo");
// Invalidar todas las cachés relacionadas con productos
await _productoCache.RemoveCacheAll();
return result;
}
}
Patrones de uso en controladores
[ApiController]
[Route("api/[controller]")]
public class ProductosController : ControllerBase
{
private readonly IProductoService _productoService;
public ProductosController(IProductoService productoService)
{
_productoService = productoService;
}
[HttpGet]
public async Task<IActionResult> GetAll()
{
// El servicio ya gestiona la caché internamente
var productos = await _productoService.ObtenerTodosAsync();
return Ok(productos);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetById(int id)
{
var producto = await _productoService.ObtenerPorIdAsync(id);
if (producto == null)
return NotFound();
return Ok(producto);
}
[HttpPost]
public async Task<IActionResult> Create(ProductoDto dto)
{
// Al crear un producto, el servicio invalidará las cachés apropiadas
var result = await _productoService.GuardarAsync(dto);
if (result.CodeError != 0)
return BadRequest(result);
return CreatedAtAction(nameof(GetById), new { id = dto.Id }, dto);
}
}
Cómo funciona internamente
Registro de claves: Cada vez que se crea una entrada en caché, la clave se registra en un diccionario para facilitar la invalidación posterior.
Agrupación por tipo: Las claves se agrupan automáticamente según el tipo genérico del servicio (TClass), lo que permite una invalidación selectiva.
Composición de claves: Las claves de caché se componen combinando el nombre del tipo, el nombre del método y los parámetros adicionales.
Invalidación jerárquica: Puedes invalidar:
- Una entrada específica
- Un grupo de entradas relacionadas con un enum
- Todas las entradas de un servicio específico
- Todas las entradas de caché de la aplicación
Mejores prácticas
Usar tipos específicos para cada servicio: Crea una instancia de ICacheHybrid<T> para cada servicio.
Definir enumeraciones para tipos de caché: Utiliza enums para categorizar diferentes tipos de caché dentro de un servicio.
Establecer duraciones apropiadas: Utiliza duraciones más cortas para datos que cambian con frecuencia.
Ser consistente con los nombres de claves: Utiliza nameof(método) para garantizar consistencia en las claves.
Invalidar con precisión: Invalida solo las entradas de caché afectadas por una operación.
Considerar el tamaño de los objetos: Evita cachear objetos muy grandes o colecciones extensas.
Monitorear el uso de memoria: Vigila el uso de memoria, especialmente en entornos de producción.
Dependencias
- Microsoft.Extensions.Caching.Hybrid: Proporciona el caché híbrido subyacente
- Nosabit.Adapters.Persistence.ICacheHybrid.Abstractions: Define las interfaces implementadas
Requisitos
- .NET 6.0 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
- Microsoft.Extensions.Caching.Hybrid (>= 9.3.0)
- Nosabit.Adapters.Persistence.ICacheHybrid.Abstractions (>= 1.2.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.