ktsu.PersistenceProvider 1.0.1

Prefix Reserved
dotnet add package ktsu.PersistenceProvider --version 1.0.1
                    
NuGet\Install-Package ktsu.PersistenceProvider -Version 1.0.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="ktsu.PersistenceProvider" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ktsu.PersistenceProvider" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="ktsu.PersistenceProvider" />
                    
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 ktsu.PersistenceProvider --version 1.0.1
                    
#r "nuget: ktsu.PersistenceProvider, 1.0.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=ktsu.PersistenceProvider&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=ktsu.PersistenceProvider&version=1.0.1
                    
Install as a Cake Tool

ktsu.PersistenceProvider

A generic persistence provider library that supports multiple storage backends for .NET applications. This library is designed to complement and integrate with ktsu.SerializationProvider and ktsu.FileSystemProvider libraries, providing a clean abstraction layer for data persistence with dependency injection support.

Features

  • Multiple Storage Backends: Memory, file system, application data, and temporary storage
  • Dependency Injection Ready: Designed for use with DI containers
  • Async/Await Support: All operations are asynchronous
  • Generic Key Support: Use any type as a key (string, Guid, int, etc.)
  • Serialization Integration: Works with any ktsu.SerializationProvider implementation
  • File System Integration: Leverages ktsu.FileSystemProvider for file operations
  • Thread-Safe: Concurrent operations are handled safely

Installation

# Install from NuGet
dotnet add package ktsu.PersistenceProvider

Quick Start

Basic Usage with Memory Provider

using ktsu.PersistenceProvider;
using ktsu.SerializationProvider;

// Create a serialization provider (implementation not shown)
ISerializationProvider serializer = new JsonSerializationProvider(); // or any other implementation

// Create a memory-based persistence provider
IPersistenceProvider<string> provider = new MemoryPersistenceProvider<string>(serializer);

// Store an object
await provider.StoreAsync("user:123", new UserSettings 
{ 
    Theme = "Dark", 
    Language = "en-US" 
});

// Retrieve the object
var settings = await provider.RetrieveAsync<UserSettings>("user:123");

// Check if an object exists
bool exists = await provider.ExistsAsync("user:123");

// Remove an object
await provider.RemoveAsync("user:123");

File System Provider

using ktsu.PersistenceProvider;
using ktsu.FileSystemProvider;
using ktsu.SerializationProvider;

// Create providers
IFileSystemProvider fileSystem = new FileSystemProvider(); // or any other implementation
ISerializationProvider serializer = new JsonSerializationProvider();

// Create file system-based persistence provider
IPersistenceProvider<string> provider = new FileSystemPersistenceProvider<string>(
    fileSystem, 
    serializer, 
    @"C:\MyApp\Data");

// Use same interface as memory provider
await provider.StoreAsync("config", new AppConfig { Version = "1.0" });
var config = await provider.RetrieveAsync<AppConfig>("config");

AppData Provider

using ktsu.PersistenceProvider;
using ktsu.FileSystemProvider;
using ktsu.SerializationProvider;

// Create providers
IFileSystemProvider fileSystem = new FileSystemProvider();
ISerializationProvider serializer = new JsonSerializationProvider();

// Create AppData-based persistence provider (stores in %APPDATA%\MyApp)
IPersistenceProvider<string> provider = new AppDataPersistenceProvider<string>(
    fileSystem, 
    serializer, 
    "MyApp");

// With optional subdirectory (stores in %APPDATA%\MyApp\Settings)
IPersistenceProvider<string> providerWithSubdir = new AppDataPersistenceProvider<string>(
    fileSystem, 
    serializer, 
    "MyApp", 
    "Settings");

// Store application data
await provider.StoreAsync("preferences", new UserPreferences 
{ 
    AutoSave = true,
    CheckForUpdates = false 
});

Temporary Storage Provider

using ktsu.PersistenceProvider;
using ktsu.FileSystemProvider;
using ktsu.SerializationProvider;

// Create temporary storage provider
IPersistenceProvider<Guid> provider = new TempPersistenceProvider<Guid>(
    fileSystemProvider, 
    serializationProvider, 
    "MyApp");

// Store temporary data
Guid sessionId = Guid.NewGuid();
await provider.StoreAsync(sessionId, new SessionData { StartTime = DateTime.UtcNow });

// Clean up on dispose
using var tempProvider = provider as TempPersistenceProvider<Guid>;
tempProvider?.Dispose(cleanupDirectory: true);

Dependency Injection

Register persistence providers in your DI container:

using Microsoft.Extensions.DependencyInjection;

var services = new ServiceCollection();

// Register dependencies
services.AddSingleton<ISerializationProvider, JsonSerializationProvider>();
services.AddSingleton<IFileSystemProvider, FileSystemProvider>();

// Register persistence providers
services.AddSingleton<IPersistenceProvider<string>>(provider =>
    new MemoryPersistenceProvider<string>(
        provider.GetRequiredService<ISerializationProvider>()));

services.AddSingleton<IPersistenceProvider<Guid>>(provider =>
    new FileSystemPersistenceProvider<Guid>(
        provider.GetRequiredService<IFileSystemProvider>(),
        provider.GetRequiredService<ISerializationProvider>(),
        @"C:\MyApp\Data"));

// Register AppData provider
services.AddSingleton<IPersistenceProvider<string>>(provider =>
    new AppDataPersistenceProvider<string>(
        provider.GetRequiredService<IFileSystemProvider>(),
        provider.GetRequiredService<ISerializationProvider>(),
        "MyApp"));

// Use in your services
services.AddTransient<IUserService, UserService>();

Available Providers

MemoryPersistenceProvider<TKey>

  • Storage: In-memory dictionary
  • Persistence: No (data lost on application exit)
  • Use Case: Caching, temporary data, testing
  • Thread Safety: Yes (ConcurrentDictionary)

FileSystemPersistenceProvider<TKey>

  • Storage: File system as JSON files
  • Persistence: Yes (survives application restart)
  • Use Case: Configuration files, user data, application state
  • Thread Safety: Yes (atomic file operations)

AppDataPersistenceProvider<TKey>

  • Storage: Application data directory (%APPDATA%\ApplicationName on Windows)
  • Persistence: Yes (survives application restart)
  • Use Case: User-specific application data, settings, preferences
  • Thread Safety: Yes (atomic file operations)

TempPersistenceProvider<TKey>

  • Storage: System temporary directory
  • Persistence: Limited (may be cleaned up by system)
  • Use Case: Temporary files, cache, session data
  • Thread Safety: Yes (atomic file operations)

Interface

public interface IPersistenceProvider<TKey> where TKey : notnull
{
    string ProviderName { get; }
    bool IsPersistent { get; }
    
    Task StoreAsync<T>(TKey key, T obj, CancellationToken cancellationToken = default);
    Task<T?> RetrieveAsync<T>(TKey key, CancellationToken cancellationToken = default);
    Task<T> RetrieveOrCreateAsync<T>(TKey key, CancellationToken cancellationToken = default) where T : new();
    Task<bool> ExistsAsync(TKey key, CancellationToken cancellationToken = default);
    Task<bool> RemoveAsync(TKey key, CancellationToken cancellationToken = default);
    Task<IEnumerable<TKey>> GetAllKeysAsync(CancellationToken cancellationToken = default);
    Task ClearAsync(CancellationToken cancellationToken = default);
}

Error Handling

All providers throw PersistenceProviderException for operation failures:

try 
{
    await provider.StoreAsync("key", data);
}
catch (PersistenceProviderException ex)
{
    // Handle persistence-specific errors
    Console.WriteLine($"Storage failed: {ex.Message}");
}

Integration with Other Libraries

This library is designed to work with:

  • ktsu.SerializationProvider: For object serialization/deserialization
  • ktsu.FileSystemProvider: For file system operations with testing support
  • Any DI Container: Microsoft.Extensions.DependencyInjection, Autofac, etc.

Building

dotnet build PersistenceProvider.sln

Testing

dotnet test PersistenceProvider.sln

Contributing

This library follows the same patterns and conventions as other ktsu.dev libraries. Please ensure:

  • All public APIs are documented with XML comments
  • Code follows established patterns from SerializationProvider and FileSystemProvider
  • Tests are included for new functionality
  • Changes are backward compatible

License

MIT License - see LICENSE file for details.

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.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.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.0.1 107 6/18/2025

## v1.0.1 (patch)

Changes since v1.0.0:

- Refactor Invoke-DotNetPack to use PackageReleaseNotesFile for referencing changelog, improving handling of special characters and command-line parsing. ([@matt-edmondson](https://github.com/matt-edmondson))
## v1.0.0 (major)

- Initial implementation ([@matt-edmondson](https://github.com/matt-edmondson))
- Enhance CHANGELOG and README with detailed implementation features; update DESCRIPTION for clarity. Adjust package references in Directory.Packages.props and improve error handling in persistence providers. Add comprehensive unit tests for AppData and Memory persistence providers. Refactor code for better readability and maintainability. ([@matt-edmondson](https://github.com/matt-edmondson))