Por qué el caché es el superpoder de cada desarrollador C#
\nImagine: su aplicación accede cada vez a la base de datos por la misma lista de ciudades o tipo de cambio. La base de datos es un recurso lento y costoso. ¿Y si le decimos que puede responder al usuario en 1 milisegundo en lugar de 100? Sí, no es magia, sino un caché de datos en C# bien implementado.
\nEl caché es una técnica de almacenamiento temporal de datos solicitados con frecuencia en un almacenamiento rápido (generalmente en RAM). En este artículo, analizaremos cómo implementar el caché en aplicaciones .NET, utilizando tanto mecanismos integrados como soluciones externas. Aprenderá cómo elegir la estrategia correcta y no caer en la trampa de los datos obsoletos.
\n\nTipos de caché en C#: desde MemoryCache hasta Redis
\nEn el ecosistema .NET existen varios enfoques para el caché. La elección depende de la arquitectura de su aplicación: monolito o microservicios, un servidor o un clúster.
\n\n1. MemoryCache integrado (System.Runtime.Caching / Microsoft.Extensions.Caching.Memory)
\nLa forma más simple y rápida es usar IMemoryCache. Los datos se almacenan en la RAM del proceso. Ideal para aplicaciones de un solo hilo o sitios web simples.
Ejemplo de registro y uso en ASP.NET Core:
\n// En Program.cs\nbuilder.Services.AddMemoryCache();\n\n// En un controlador o servicio\npublic class WeatherService\n{\n private readonly IMemoryCache _cache;\n\n public WeatherService(IMemoryCache cache)\n {\n _cache = cache;\n }\n\n public async Task<string> GetWeatherAsync(string city)\n {\n string cacheKey = $"weather_{city}";\n\n // Intentamos obtener datos del caché\n if (_cache.TryGetValue(cacheKey, out string cachedData))\n {\n return cachedData;\n }\n\n // Si no hay datos, los cargamos (por ejemplo, desde una API)\n string weatherData = await FetchWeatherFromApi(city);\n\n // Guardamos en caché por 10 minutos\n var cacheEntryOptions = new MemoryCacheEntryOptions()\n .SetAbsoluteExpiration(TimeSpan.FromMinutes(10));\n\n _cache.Set(cacheKey, weatherData, cacheEntryOptions);\n\n return weatherData;\n }\n}\nMétodos clave: TryGetValue, Set, Remove. Observe las políticas de expiración: tiempo absoluto (los datos expiran exactamente después de N minutos) y tiempo deslizante (los datos viven mientras se accede a ellos y N minutos después de la última solicitud).
2. Caché distribuido: Redis a través de IDistributedCache
\nSi tiene varias instancias de la aplicación (granja web, microservicios), MemoryCache no es adecuado: cada servidor almacenará su propia copia. Redis viene al rescate. Funciona como un servidor separado, común para todas las instancias.
\nConexión a Redis en C#:
\n// Instale el paquete: Microsoft.Extensions.Caching.StackExchangeRedis\nbuilder.Services.AddStackExchangeRedisCache(options =>\n{\n options.Configuration = "localhost:6379";\n options.InstanceName = "SampleInstance";\n});\n\n// Uso a través de IDistributedCache\npublic class ProductService\n{\n private readonly IDistributedCache _cache;\n\n public ProductService(IDistributedCache cache)\n {\n _cache = cache;\n }\n\n public async Task<Product> GetProductAsync(int id)\n {\n string cacheKey = $"product_{id}";\n var cachedProduct = await _cache.GetStringAsync(cacheKey);\n\n if (cachedProduct != null)\n {\n return JsonSerializer.Deserialize<Product>(cachedProduct);\n }\n\n var product = await FetchProductFromDb(id);\n var serialized = JsonSerializer.Serialize(product);\n\n await _cache.SetStringAsync(cacheKey, serialized, new DistributedCacheEntryOptions\n {\n AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30)\n });\n\n