Community.Microsoft.Extensions.Caching.PostgreSql 5.0.0

dotnet add package Community.Microsoft.Extensions.Caching.PostgreSql --version 5.0.0                
NuGet\Install-Package Community.Microsoft.Extensions.Caching.PostgreSql -Version 5.0.0                
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="Community.Microsoft.Extensions.Caching.PostgreSql" Version="5.0.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Community.Microsoft.Extensions.Caching.PostgreSql --version 5.0.0                
#r "nuget: Community.Microsoft.Extensions.Caching.PostgreSql, 5.0.0"                
#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.
// Install Community.Microsoft.Extensions.Caching.PostgreSql as a Cake Addin
#addin nuget:?package=Community.Microsoft.Extensions.Caching.PostgreSql&version=5.0.0

// Install Community.Microsoft.Extensions.Caching.PostgreSql as a Cake Tool
#tool nuget:?package=Community.Microsoft.Extensions.Caching.PostgreSql&version=5.0.0                

PostgreSQL Distributed Cache for .NET Core | Community Edition

Nuget

Introduction

Community.Microsoft.Extensions.Caching.PostgreSQL is a robust and scalable distributed cache implementation for ASP.NET Core applications using PostgreSQL 11+ as the underlying data store. This package provides a simple and efficient way to leverage your existing PostgreSQL infrastructure for caching, offering a cost-effective alternative to dedicated caching servers. Ideal for scenarios where minimizing infrastructure complexity and maximizing performance is critical.

This library allows you to seamlessly integrate caching into your ASP.NET / .NET Core applications using the standard IDistributedCache interface. It's designed to be production-ready and configurable, giving you fine-grained control over caching behavior.

Why choose this package?

  1. If you already use PostgreSQL, this package avoids the need for additional caching solutions like Redis, reducing infrastructure overhead.
  2. Optimized for fast read and write operations with PostgreSQL, providing excellent caching performance. It is not a competitor to Redis, but it is a good alternative for some scenarios.
  3. Dstributed cache supports scaling of multiple instances and high loads.
  4. Simple setup process using standard ASP.NET Core / .NET Core dependency injection.
  5. Provides flexible configuration options including cache expiration policies, background cleanup tasks, read-only mode, and more.
  6. Benefit from the power of open source and a community-driven approach to caching.

Table of Contents

  1. Getting Started
  2. Installation
  3. Basic Configuration
  4. Configuration Options
  5. Usage Examples
  6. Running the Console Sample
  7. Running the React+WebApi Web Sample
  8. Change Log
  9. Contributing
  10. License
  11. FAQ
  12. Troubleshooting

Getting Started

1. Installation

Install the package via the .NET CLI:

dotnet add package Community.Microsoft.Extensions.Caching.PostgreSql

2. Basic Configuration

Add the following line to your Startup.cs or Program.cs's ConfigureServices method:

services.AddDistributedPostgreSqlCache(setup =>
{
    setup.ConnectionString = configuration["ConnectionString"];
    setup.SchemaName = configuration["SchemaName"];
    setup.TableName = configuration["TableName"];
    setup.DisableRemoveExpired = configuration["DisableRemoveExpired"];
    // Optional - DisableRemoveExpired default is FALSE
    setup.CreateInfrastructure = configuration["CreateInfrastructure"];
    // CreateInfrastructure is optional, default is TRUE
    // This means that every time the application starts the
    // creation of the table and database functions will be verified.
    setup.ExpiredItemsDeletionInterval = TimeSpan.FromMinutes(30);
    // ExpiredItemsDeletionInterval is optional
    // This is the periodic interval to scan and delete expired items in the cache. Default is 30 minutes.
    // Minimum allowed is 5 minutes. - If you need less than this please share your use case 😁, just for curiosity...
});
Configuring with IServiceProvider access:
services.AddDistributedPostgreSqlCache((serviceProvider, setup) =>
{
    // IConfiguration is used as an example here
    var configuration = serviceProvider.GetRequiredService<IConfiguration>();
    setup.ConnectionString = configuration["ConnectionString"];
    ...
});
Configuring via IConfigureOptions<PostgreSqlCacheOptions>

Use:

services.AddDistributedPostgreSqlCache();

And implement and register:

IConfigureOptions<PostgreSqlCacheOptions>

Configuration Options

DisableRemoveExpired = True use case (default false):

When you have 2 or more instances/microservices/processes and you want to leave only one instance to remove expired items.

  • Note 1: This is not mandatory; assess whether it fits your needs.
  • Note 2: If you have only one instance and set this to True, expired items will not be automatically removed. When calling GetItem, expired items are filtered out. In this scenario, you are responsible for manually removing the expired keys or updating them.

UpdateOnGetCacheItem = false use case (default true):

If you (or the implementation using this cache) are explicitly calling IDistributedCache.Refresh to update the sliding window, you can turn off UpdateOnGetCacheItem to remove the extra DB expiration update call prior to reading the cached value. This is useful when used with ASP.NET Core Session handling.

services.AddDistributedPostgreSqlCache((serviceProvider, setup) =>
{
    ...
    setup.UpdateOnGetCacheItem = false;
    // Or
    var configuration = serviceProvider.GetRequiredService<IConfiguration>();
    setup.UpdateOnGetCacheItem = configuration["UpdateOnGetCacheItem"];
    ...
});

ReadOnlyMode = true use case (default false):

For read-only databases, or if the database user lacks write permissions, you can set ReadOnlyMode = true.

  • Note 1: This will disable sliding expiration; only absolute expiration will work.
  • Note 2: This can improve performance, but you will not be able to change any cache values.
services.AddDistributedPostgreSqlCache((serviceProvider, setup) =>
{
    ...
    setup.ReadOnlyMode = true;
    // Or
    var configuration = serviceProvider.GetRequiredService<IConfiguration>();
    setup.ReadOnlyMode = configuration["UpdateOnGetCacheItem"];
    ...
});

CreateInfrastructure = true use case:

This creates the table and schema for storing the cache (names are configurable) if they don't exist.

Usage Examples

Basic Example

    // This is extracted from the React+WebApi WebSample

    private readonly IDistributedCache _cache;

    public WeatherForecastController(IDistributedCache cache)
    {
        _cache = cache;
    }

    [HttpGet]
    public async Task<IEnumerable<WeatherForecast>> Get()
    {
       var cachedValue = await _cache.GetStringAsync("weather-forecast");
       if(string.IsNullOrEmpty(cachedValue))
       {
          //Do stuff to fetch data...
          var forecast = Enumerable.Range(1, 5).Select(index => new WeatherForecast
          {
              Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
              TemperatureC = Random.Shared.Next(-20, 55),
              Summary = Summaries[Random.Shared.Next(Summaries.Length)]
          })
          .ToArray();
          var byteArray = JsonSerializer.SerializeToUtf8Bytes(forecast);
          await _cache.SetAsync("weather-forecast", byteArray, new DistributedCacheEntryOptions
          {
              AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(60)
          });

          return forecast;
       }

       var result = JsonSerializer.Deserialize<WeatherForecast[]>(cachedValue);
       return result;
    }

Using Custom Options

 services.AddDistributedPostgreSqlCache((serviceProvider, setup) =>
 {
     var configuration = serviceProvider.GetRequiredService<IConfiguration>();
     setup.ConnectionString = configuration["CacheConnectionString"];
     setup.SchemaName = "my_custom_cache_schema";
     setup.TableName = "my_custom_cache_table";
     setup.DisableRemoveExpired = true;
     setup.CreateInfrastructure = true;
     setup.ExpiredItemsDeletionInterval = TimeSpan.FromMinutes(15);
     setup.UpdateOnGetCacheItem = false;
     setup.ReadOnlyMode = true;
 });

Running the Console Sample

You will need a local PostgreSQL server with the following:

  1. Server listening on port 5432 at localhost
  2. The password of your postgres account, if not attached already to your user.
  3. Clone this repository.
  4. Run the following commands inside PostgreSqlCacheSample:
dotnet restore
prepare-database.cmd -create
dotnet run

Running the React+WebApi WebSample project

You will need a local PostgreSQL server with the following:

  1. Server listening on port 5432 at localhost
  2. The password of your postgres account, if not attached already to your user.
  3. You also need npm and node installed on your development machine.
  4. Clone this repository.
  5. Run the following commands inside the WebSample directory:
dotnet restore
prepare-database.cmd -create // windows
chmod +x prepare-database.sh // linux - just once to make the script executable
./prepare-database.sh -create // linux
dotnet run

It may take some time for npm to restore the packages.

Then, you can delete the database using:

prepare-database.cmd -erase // windows
./prepare-database.sh -erase // linux

if you don't want to use the bash/cmd script, you can run the SQL script directly on your PostgreSQL database.

Change Log

  1. v5.0.0 - Added support for .NET 9
    1. [BREAKING CHANGE] - Dropped support for .NETStandard2.0
    2. [BREAKING CHANGE] - Supports .NET 9, .NET 8 and .NET 6
  2. v4.0.1 - Added support for .NET 7
    1. [BREAKING CHANGE] - Dropped support for .NET 5
    2. [BREAKING CHANGE] - Now uses stored procedures (won't work with PostgreSQL ⇐ 10, use version 3)
  3. v3.1.2 - Removed dependency for IHostApplicationLifetime if not supported on the platform (e.g., AWS) - issue #28
  4. v3.1.0 - Added log messages on Debug Level, multitarget .NET 5 and .NET 6, dropped support for netstandard2.0, fixed sample to match multi-targeting and sample database.
  5. v3.0.2 - CreateInfrastructure also creates the schema - issue #8
  6. v3.0.1 - Added DisableRemoveExpired configuration; if TRUE, the cache instance won't delete expired items.
  7. v3.0
    1. [BREAKING CHANGE] - Direct instantiation not preferred.
    2. Single-threaded loop remover.
  8. v2.0.x - Updated everything to .NET 5.0, more detailed sample project.
  9. v1.0.8 - Updated to the latest dependencies.

Contributing

We welcome contributions! Please see our Contributing Guidelines for more details on how to get involved.

License

MIT License

FAQ

Q: What versions of PostgreSQL are supported?

A: This package supports PostgreSQL 11 and higher. For older versions (<= 10), use older versions of this package (<= 3.1.2).

Q: How do I handle database connection issues?

A: Ensure your connection string is correct and that your database server is accessible. Verify your username, password, and host settings.

Q: Is this package production-ready?

A: Yes, this package is designed for production use. It includes features like background expired item removal and configurable options, but it's always recommended to thoroughly test it in your specific environment.

Q: What are the performance characteristics of this library?

A: The library is optimized to perform well when using PostgreSQL. The performance of this library is tied to your database, so make sure your server is appropriately configured. We have plans to provide benchmarks in the future.

Troubleshooting

Please check the Github issues page to see if the issue is already reported. If not, please create a new issue describing the problem with all the necessary details to reproduce it.

Known issues:

  • The library does not perform well with large objects in the cache due to the nature of PostgreSQL, large objects may cause performance bottlenecks.

This is a fork from repo

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on Community.Microsoft.Extensions.Caching.PostgreSql:

Package Downloads
BIA.Net.Core.Presentation.Common

Presentation features layer classes for BIA.Net Core Framework

SoftwaredeveloperDotAt.Infrastructure.Core.PostgreSQL

Library for base .NET Classes

Pipoburgos.SharedKernel.Infrastructure.EntityFrameworkCore.PostgreSQL

EntityFrameworkCore.PostgreSQL infrastructure implementations

GitHub repositories (1)

Showing the top 1 popular GitHub repositories that depend on Community.Microsoft.Extensions.Caching.PostgreSql:

Repository Stars
simpleidserver/SimpleIdServer
OpenID, OAuth 2.0, SCIM2.0, UMA2.0, FAPI, CIBA & OPENBANKING Framework for ASP.NET Core
Version Downloads Last updated
5.0.0 166 12/30/2024
4.0.6 51,023 8/20/2024
4.0.4 146,084 10/2/2023
4.0.2 68,780 12/27/2022
4.0.1 4,054 12/6/2022
3.1.2 90,462 5/25/2022
3.1.1 25,742 2/22/2022
3.1.0 11,388 12/20/2021
3.0.3.2 46,615 5/14/2021
3.0.2 1,178 4/4/2021
3.0.1 21,923 1/17/2021
3.0.0 823 1/9/2021
2.0.7 2,564 11/27/2020
1.0.30 68,767 4/20/2019
1.0.7 3,192 3/24/2018
1.0.5 873 3/22/2018
1.0.0 1,027 3/22/2018