# Caching

## 1. In-Memory Cache

**In-Memory Cache** stores data directly in the application's memory. This type of cache is very fast because the data is stored and accessed directly from RAM.

*   **MemoryCache**: The `MemoryCache` class in the `System.Runtime.Caching` namespace provides a simple way to store and retrieve data from memory.

    **Example:**

    ```csharp
    using System;
    using System.Runtime.Caching;

    class Program
    {
        static void Main()
        {
            ObjectCache cache = MemoryCache.Default;
            string key = "myKey";
            string value = "myValue";

            // Add data to cache with a lifetime of 1 minute
            cache.Set(key, value, DateTimeOffset.Now.AddMinutes(1));

            // Retrieve data from cache
            var cachedValue = cache.Get(key) as string;
            Console.WriteLine(cachedValue);  // Output: myValue
        }
    }
    ```
* **IMemoryCache**: In `Microsoft.Extensions.Caching.Memory`, `IMemoryCache` is a service that provides a mechanism for storing data in memory in ASP.NET Core applications.

What are the key features of this library?

1. Strongly Typed: Unlike the earlier MemoryCache, IMemoryCache is strongly typed, reducing errors and improving code readability.
2. Dependency Injection Friendly: IMemoryCache is designed to be used with dependency injection, making it easy to manage and test.
3. Expiration Policies:
4. Absolute Expiration: The cache entry will expire after a set duration.
5. Sliding Expiration: The cache entry will expire if it's not accessed within a set duration.
6. Expiration Tokens: These allow cache entries to be evicted based on external triggers, like file changes.
7. Size Limitations: You can set a size limit for the cache and define the size for each entry, helping to manage memory usage effectively.
8. Eviction Callbacks: Callbacks can be registered to execute custom logic when a cache entry is evicted.
9. Thread Safety: IMemoryCache is thread-safe, allowing concurrent access by multiple threads.

**Example:**

```csharp
using System;
using Microsoft.Extensions.Caching.Memory;

class Program
{
    static void Main()
    {
        IMemoryCache cache = new MemoryCache(new MemoryCacheOptions());
        string key = "myKey";
        string value = "myValue";

        // Add data to cache
        cache.Set(key, value, TimeSpan.FromMinutes(1));

        // Retrieve data from cache
        var cachedValue = cache.Get(key) as string;
        Console.WriteLine(cachedValue);  // Output: myValue
    }
}
```

## 2. Distributed Cache

**Distributed Cache** stores data on one or more external servers, allowing shared caching between multiple instances or applications.

*   **Redis Cache**: Redis is an in-memory data structure store that can be used as a distributed cache.

    **Example:**

    ```csharp
    using Microsoft.Extensions.Caching.Distributed;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using StackExchange.Redis;

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddStackExchangeRedisCache(options =>
            {
                options.Configuration = "localhost:6379";
                options.InstanceName = "SampleInstance";
            });
        }
    }
    ```
*   **SQL Server Cache**: Uses SQL Server to store cache data.

    **Example:**

    ```csharp
    using Microsoft.Extensions.Caching.Distributed;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDistributedSqlServerCache(options =>
            {
                options.ConnectionString = "Server=myServer;Database=myDb;User Id=myUser;Password=myPassword;";
                options.SchemaName = "dbo";
                options.TableName = "CacheTable";
            });
        }
    }
    ```

## 3. Output Cache

**Output Cache** stores the output of actions or entire pages in web applications.

*   **Output Caching in ASP.NET MVC/Web API**: Stores the result of controller actions to speed up HTTP responses for similar requests.

    **Example:**

    ```csharp
    using System.Web.Mvc;

    public class HomeController : Controller
    {
        [OutputCache(Duration = 60)]
        public ActionResult Index()
        {
            return View();
        }
    }
    ```
*   **Response Caching Middleware in ASP.NET Core**: Middleware that stores the results of HTTP requests to reuse for subsequent requests.

    **Example:**

    ```csharp
    using Microsoft.AspNetCore.Builder;
    using Microsoft.Extensions.DependencyInjection;

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddResponseCaching();
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseResponseCaching();

            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    context.Response.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue()
                    {
                        Public = true,
                        MaxAge = TimeSpan.FromSeconds(60)
                    };
                    await context.Response.WriteAsync("Hello World!");
                });
            });
        }
    }
    ```

## Summary

In C#, the common types of caching include:

1. **In-Memory Cache**: Using `MemoryCache` or `IMemoryCache`.
2. **Distributed Cache**: Using distributed systems like Redis or SQL Server.
3. **Output Cache**: Used in web applications to store the results of actions or pages.
