A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/reactiveui/akavache below:

reactiveui/Akavache: An asynchronous, persistent key-value store created for writing desktop and mobile applications, based on SQLite3. Akavache is great for both storing important data as well as cached local data that expires.


Akavache V11.0: An Asynchronous Key-Value Store for Native Applications

Akavache is an asynchronous, persistent (i.e., writes to disk) key-value store created for writing desktop and mobile applications in C#, based on SQLite3. Akavache is great for both storing important data (i.e., user settings) as well as cached local data that expires.

Akavache V11.0 introduces a new Builder Pattern for initialization, improved serialization support, and enhanced cross-serializer compatibility:

Akavache V11.0 represents a significant evolution in the library's architecture, developed through extensive testing and community feedback in our incubator project. The new features and improvements in V11.0 were first prototyped and battle-tested in the ReactiveMarbles.CacheDatabase repository, which served as an experimental ground for exploring new caching concepts and architectural patterns.

Key Development Milestones:

This careful incubation process ensured that V11.0 delivers not just new features, but a more robust, flexible, and maintainable caching solution that builds upon years of community experience and testing. The ReactiveMarbles organization continues to serve as a proving ground for innovative reactive programming concepts that eventually make their way into the broader ReactiveUI ecosystem.

<PackageReference Include="Akavache.Sqlite3" Version="11.0.*" />
<PackageReference Include="Akavache.SystemTextJson" Version="11.0.*" />
using Akavache.Core;
using Akavache.SystemTextJson;
using Akavache.Sqlite3;

// Initialize with the builder pattern
CacheDatabase.Initialize(builder =>
    builder.WithApplicationName("MyApp")
           .WithSerializer(new SystemJsonSerializer())
           .WithSqliteDefaults());
// Store an object
var user = new User { Name = "John", Email = "john@example.com" };
await CacheDatabase.UserAccount.InsertObject("current_user", user);

// Retrieve an object
var cachedUser = await CacheDatabase.UserAccount.GetObject<User>("current_user");

// Store with expiration
await CacheDatabase.LocalMachine.InsertObject("temp_data", someData, DateTimeOffset.Now.AddHours(1));

// Get or fetch pattern
var data = await CacheDatabase.LocalMachine.GetOrFetchObject("api_data", 
    async () => await httpClient.GetFromJsonAsync<ApiResponse>("https://api.example.com/data"));

Akavache V11.0 uses a modular package structure. Choose the packages that match your needs:

Core Package (Included with Serializers, In Memory only)
<PackageReference Include="Akavache" Version="11.0.**" />
Sqlite Storage Backends (recommended)
<!-- SQLite persistence -->
<PackageReference Include="Akavache.Sqlite3" Version="11.0.**" />

<!-- Encrypted SQLite persistence -->
<PackageReference Include="Akavache.EncryptedSqlite3" Version="11.0.**" />
Serializers (Choose One (Required!))
<!-- System.Text.Json (fastest, .NET native) -->
<PackageReference Include="Akavache.SystemTextJson" Version="11.0.**" />

<!-- Newtonsoft.Json (most compatible) -->
<PackageReference Include="Akavache.NewtonsoftJson" Version="11.0.**" />
<!-- Image/Bitmap support -->
<PackageReference Include="Akavache.Drawing" Version="11.0.**" />

<!-- Settings helpers -->
<PackageReference Include="Akavache.Settings" Version="11.0.**" />
  1. Initialization Method: The BlobCache.ApplicationName and Registrations.Start() methods are replaced with the builder pattern
  2. Package Structure: Akavache is now split into multiple packages
  3. Serializer Registration: Must explicitly register a serializer before use
// V10.x initialization
BlobCache.ApplicationName = "MyApp";
// or
Akavache.Registrations.Start("MyApp");

// Usage
var data = await BlobCache.UserAccount.GetObject<MyData>("key");
await BlobCache.LocalMachine.InsertObject("key", myData);
// V11.0 initialization

CacheDatabase.Initialize(builder =>
    builder.WithApplicationName("MyApp")
           .WithSerializer(new SystemJsonSerializer()) // Required!
           .WithSqliteDefaults());

// Usage (same API)
var data = await CacheDatabase.UserAccount.GetObject<MyData>("key");
await CacheDatabase.LocalMachine.InsertObject("key", myData);

Create this helper method to ease migration:

public static class AkavacheMigration
{
    public static void InitializeV11(string appName)
    {
        // Initialize with SQLite (most common V10.x setup)
        CacheDatabase.Initialize(builder =>
            builder.WithApplicationName(appName)
                   .WithSerializer(new SystemJsonSerializer()) // Choose your preferred serializer, Required!
                   .WithSqliteDefaults());
    }
}

// Then in your app:
AkavacheMigration.InitializeV11("MyApp");

Akavache V11.0 uses a fluent builder pattern for configuration:

CacheDatabase.Initialize(builder =>
    builder.WithApplicationName("MyApp")           // Required
           .WithSerializer(new SystemJsonSerializer()) // Custom serializer
           .WithSqliteDefaults());                   // SQLite persistence
1. In-Memory Only (for testing or non retensive applications)
CacheDatabase.Initialize(builder =>
    builder.WithApplicationName("TestApp")
           .WithSerializer(new SystemJsonSerializer()) // Custom serializer
           .WithInMemoryDefaults());
CacheDatabase.Initialize(builder =>
    builder.WithApplicationName("MyApp")
           .WithSerializer(new SystemJsonSerializer()) // Custom serializer
           .WithSqliteDefaults());
CacheDatabase.Initialize(builder =>
    builder.WithApplicationName("MyApp")
           .WithSerializer(new SystemJsonSerializer()) // Custom serializer
           .WithSqliteDefaults("mySecretPassword"));
4. Custom Cache Instances
CacheDatabase.Initialize(builder =>
    builder.WithApplicationName("MyApp")
           .WithSerializer(new SystemJsonSerializer()) // Custom serializer
           .WithUserAccount(new SqliteBlobCache("custom-user.db"))
           .WithLocalMachine(new SqliteBlobCache("custom-local.db"))
           .WithSecure(new EncryptedSqliteBlobCache("secure.db", "password"))
           .WithInMemory(new InMemoryBlobCache()));
// Set global DateTime behavior
CacheDatabase.ForcedDateTimeKind = DateTimeKind.Utc;

CacheDatabase.Serializer = new SystemJsonSerializer();
CacheDatabase.Initialize(builder => builder.WithApplicationName("MyApp").WithSqliteDefaults());

Akavache V11.0 supports multiple serialization formats with automatic cross-compatibility.

System.Text.Json (Recommended)

Best for: New applications, performance-critical scenarios, .NET native support

CacheDatabase.Serializer = new SystemJsonSerializer();

Features:

Configuration:

var serializer = new SystemJsonSerializer()
{
    UseBsonFormat = false, // true for max compatibility with old data
    Options = new JsonSerializerOptions
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        WriteIndented = false
    }
};
CacheDatabase.Serializer = serializer;
Newtonsoft.Json (Maximum Compatibility)

Best for: Migrating from older Akavache versions, complex serialization needs

CacheDatabase.Serializer = new NewtonsoftSerializer();

Features:

Configuration:

var serializer = new NewtonsoftSerializer()
{
    UseBsonFormat = true, // Recommended for Akavache compatibility
    Options = new JsonSerializerSettings
    {
        DateTimeZoneHandling = DateTimeZoneHandling.Utc,
        NullValueHandling = NullValueHandling.Ignore
    }
};
CacheDatabase.Serializer = serializer;

For maximum compatibility with existing Akavache data:

// System.Text.Json with BSON support
CacheDatabase.Serializer = new SystemJsonBsonSerializer();

// Newtonsoft.Json with BSON support  
CacheDatabase.Serializer = new NewtonsoftBsonSerializer();
Cross-Serializer Compatibility

V11.0 can automatically read data written by different serializers:

// Data written with Newtonsoft.Json BSON can be read by System.Text.Json
// Data written with System.Text.Json can be read by Newtonsoft.Json
// Automatic format detection handles the conversion

Akavache provides four types of caches, each with different characteristics:

Purpose: User settings and preferences that should persist and potentially sync across devices.

// Store user preferences
var settings = new UserSettings { Theme = "Dark", Language = "en-US" };
await CacheDatabase.UserAccount.InsertObject("user_settings", settings);

// Retrieve preferences
var userSettings = await CacheDatabase.UserAccount.GetObject<UserSettings>("user_settings");

Platform Behavior:

Purpose: Cached data that can be safely deleted by the system.

// Cache API responses
var apiData = await httpClient.GetFromJsonAsync<ApiResponse>("https://api.example.com/data");
await CacheDatabase.LocalMachine.InsertObject("api_cache", apiData, DateTimeOffset.Now.AddHours(6));

// Retrieve with fallback
var cachedData = await CacheDatabase.LocalMachine.GetOrFetchObject("api_cache",
    () => httpClient.GetFromJsonAsync<ApiResponse>("https://api.example.com/data"));

Platform Behavior:

Purpose: Encrypted storage for sensitive data like credentials and API keys.

// Store credentials
await CacheDatabase.Secure.SaveLogin("john.doe", "secretPassword", "myapp.com");

// Retrieve credentials
var loginInfo = await CacheDatabase.Secure.GetLogin("myapp.com");
Console.WriteLine($"User: {loginInfo.UserName}, Password: {loginInfo.Password}");

// Store API keys
await CacheDatabase.Secure.InsertObject("api_key", "sk-1234567890abcdef");
var apiKey = await CacheDatabase.Secure.GetObject<string>("api_key");

Purpose: Temporary storage that doesn't persist between app sessions.

// Cache session data
var sessionData = new SessionInfo { UserId = 123, SessionToken = "abc123" };
await CacheDatabase.InMemory.InsertObject("current_session", sessionData);

// Fast temporary storage
await CacheDatabase.InMemory.InsertObject("temp_calculation", expensiveResult);
// Store simple objects
await CacheDatabase.UserAccount.InsertObject("key", myObject);

// Store with expiration
await CacheDatabase.LocalMachine.InsertObject("temp_key", data, DateTimeOffset.Now.AddMinutes(30));

// Store multiple objects
var keyValuePairs = new Dictionary<string, MyData>
{
    ["key1"] = new MyData { Value = 1 },
    ["key2"] = new MyData { Value = 2 }
};
await CacheDatabase.UserAccount.InsertObjects(keyValuePairs);

// Store raw bytes
await CacheDatabase.LocalMachine.Insert("raw_key", Encoding.UTF8.GetBytes("Hello World"));
// Get single object
var data = await CacheDatabase.UserAccount.GetObject<MyData>("key");

// Get multiple objects
var keys = new[] { "key1", "key2", "key3" };
var results = await CacheDatabase.UserAccount.GetObjects<MyData>(keys).ToList();

// Get all objects of a type
var allData = await CacheDatabase.UserAccount.GetAllObjects<MyData>().ToList();

// Get raw bytes
var rawData = await CacheDatabase.LocalMachine.Get("raw_key");
// Handle missing keys
try
{
    var data = await CacheDatabase.UserAccount.GetObject<MyData>("nonexistent_key");
}
catch (KeyNotFoundException)
{
    // Key not found
    var defaultData = new MyData();
}

// Use fallback pattern
var data = await CacheDatabase.UserAccount.GetObject<MyData>("key")
    .Catch(Observable.Return(new MyData()));
// Remove single object
await CacheDatabase.UserAccount.InvalidateObject<MyData>("key");

// Remove multiple objects
await CacheDatabase.UserAccount.InvalidateObjects<MyData>(new[] { "key1", "key2" });

// Remove all objects of a type
await CacheDatabase.UserAccount.InvalidateAllObjects<MyData>();

// Remove all data
await CacheDatabase.UserAccount.InvalidateAll();

The most common pattern for caching remote data:

// Basic get-or-fetch
var userData = await CacheDatabase.LocalMachine.GetOrFetchObject("user_profile",
    async () => await apiClient.GetUserProfile(userId));

// With expiration
var weatherData = await CacheDatabase.LocalMachine.GetOrFetchObject("weather",
    async () => await weatherApi.GetCurrentWeather(),
    DateTimeOffset.Now.AddMinutes(30));

// With custom fetch observable
var liveData = await CacheDatabase.LocalMachine.GetOrFetchObject("live_data",
    () => Observable.Interval(TimeSpan.FromSeconds(5))
                   .Select(_ => DateTime.Now.ToString()));

Returns cached data immediately, then fetches fresh data:

// Subscribe to get both cached and fresh data
CacheDatabase.LocalMachine.GetAndFetchLatest("news_feed",
    () => newsApi.GetLatestNews())
    .Subscribe(news => 
    {
        // This will be called twice:
        // 1. Immediately with cached data (if available)
        // 2. When fresh data arrives from the API
        UpdateUI(news);
    });
// Download and cache URLs
var imageData = await CacheDatabase.LocalMachine.DownloadUrl("https://example.com/image.jpg");

// With custom headers
var headers = new Dictionary<string, string>
{
    ["Authorization"] = "Bearer " + token,
    ["User-Agent"] = "MyApp/1.0"
};
var apiResponse = await CacheDatabase.LocalMachine.DownloadUrl("https://api.example.com/data", 
    HttpMethod.Get, headers);

// Force fresh download
var freshData = await CacheDatabase.LocalMachine.DownloadUrl("https://api.example.com/live", 
    fetchAlways: true);
Login/Credential Management
// Save login credentials (encrypted)
await CacheDatabase.Secure.SaveLogin("username", "password", "myapp.com");

// Retrieve credentials
var loginInfo = await CacheDatabase.Secure.GetLogin("myapp.com");
Console.WriteLine($"User: {loginInfo.UserName}");

// Multiple hosts
await CacheDatabase.Secure.SaveLogin("user1", "pass1", "api.service1.com");
await CacheDatabase.Secure.SaveLogin("user2", "pass2", "api.service2.com");

// Remove credentials
await CacheDatabase.Secure.EraseLogin("myapp.com");
// Cache for relative time periods
await CacheDatabase.LocalMachine.InsertObject("data", myData, TimeSpan.FromMinutes(30).FromNow());

// Use in get-or-fetch
var cachedData = await CacheDatabase.LocalMachine.GetOrFetchObject("api_data",
    () => FetchFromApi(),
    1.Hours().FromNow());
// Use custom scheduler for background operations
CacheDatabase.TaskpoolScheduler = TaskPoolScheduler.Default;

// Or use a custom scheduler
CacheDatabase.TaskpoolScheduler = new EventLoopScheduler();
// Get all keys (for debugging)
var allKeys = await CacheDatabase.UserAccount.GetAllKeys().ToList();

// Check when item was created
var createdAt = await CacheDatabase.UserAccount.GetCreatedAt("my_key");
if (createdAt.HasValue)
{
    Console.WriteLine($"Item created at: {createdAt.Value}");
}

// Get creation times for multiple keys
var creationTimes = await CacheDatabase.UserAccount.GetCreatedAt(new[] { "key1", "key2" })
    .ToList();
// Force flush all pending operations
await CacheDatabase.UserAccount.Flush();

// Vacuum database (SQLite only - removes deleted data)
await CacheDatabase.UserAccount.Vacuum();

// Flush specific object type
await CacheDatabase.UserAccount.Flush(typeof(MyDataType));
// Store different types with one operation
var mixedData = new Dictionary<string, object>
{
    ["string_data"] = "Hello World",
    ["number_data"] = 42,
    ["object_data"] = new MyClass { Value = "test" },
    ["date_data"] = DateTime.Now
};

await CacheDatabase.UserAccount.InsertObjects(mixedData);

Akavache.Drawing provides comprehensive image caching and bitmap manipulation functionality for Akavache applications. Built on Splat, it offers cross-platform support for loading, caching, and manipulating images with enhanced features beyond basic blob storage.

<PackageReference Include="Akavache.Drawing" Version="11.0.1" />

Akavache.Drawing requires:

1. Initialize Drawing Support
using Akavache.Core;
using Akavache.Drawing;
using Akavache.SystemTextJson;
using Splat;

// Initialize Akavache with drawing support
CacheDatabase.Initialize(builder =>
    builder.WithApplicationName("MyImageApp")
           .WithSerializer(new SystemJsonSerializer())
           .WithSqliteDefaults());

// Register platform-specific bitmap loader using Splat (if needed (Net 8.0+))
Locator.CurrentMutable.RegisterPlatformBitmapLoader();
2. Load Images from Cache
// Load image from cache
var image = await CacheDatabase.LocalMachine.LoadImage("user_avatar");

// Load with custom sizing
var thumbnail = await CacheDatabase.LocalMachine.LoadImage("user_avatar", 150, 150);

// Load with error handling
try
{
    var profileImage = await CacheDatabase.UserAccount.LoadImage("profile_pic");
    DisplayImage(profileImage);
}
catch (KeyNotFoundException)
{
    // Image not found in cache
    ShowDefaultImage();
}
// Download and cache image from URL
var imageFromUrl = await CacheDatabase.LocalMachine
    .LoadImageFromUrl("https://example.com/images/photo.jpg");

// With custom expiration
var tempImage = await CacheDatabase.LocalMachine
    .LoadImageFromUrl("https://api.example.com/temp-image.png", 
                     absoluteExpiration: DateTimeOffset.Now.AddHours(1));

// Force fresh download (bypass cache)
var freshImage = await CacheDatabase.LocalMachine
    .LoadImageFromUrl("https://api.example.com/live-feed.jpg", fetchAlways: true);

// With custom key
var namedImage = await CacheDatabase.LocalMachine
    .LoadImageFromUrl("user_background", "https://example.com/bg.jpg");
// Save image to cache
await CacheDatabase.LocalMachine.SaveImage("user_photo", bitmap);

// Save with expiration
await CacheDatabase.LocalMachine.SaveImage("temp_image", bitmap, 
    DateTimeOffset.Now.AddDays(7));

// Convert bitmap to bytes for manual storage
var imageBytes = await bitmap.ImageToBytes().FirstAsync();
await CacheDatabase.LocalMachine.Insert("raw_image_data", imageBytes);
// Load multiple images at once
var imageKeys = new[] { "image1", "image2", "image3" };
var loadedImages = await CacheDatabase.LocalMachine
    .LoadImages(imageKeys, desiredWidth: 200, desiredHeight: 200)
    .ToList();

foreach (var kvp in loadedImages)
{
    Console.WriteLine($"Loaded {kvp.Key}: {kvp.Value.Width}x{kvp.Value.Height}");
}

// Preload images from URLs (background caching)
var urls = new[]
{
    "https://example.com/image1.jpg",
    "https://example.com/image2.jpg",
    "https://example.com/image3.jpg"
};

await CacheDatabase.LocalMachine.PreloadImagesFromUrls(urls, 
    DateTimeOffset.Now.AddDays(1));
// Load image with automatic fallback
var defaultImageBytes = File.ReadAllBytes("default-avatar.png");

var userAvatar = await CacheDatabase.UserAccount
    .LoadImageWithFallback("user_avatar", defaultImageBytes, 100, 100);

// Load from URL with fallback
var profileImage = await CacheDatabase.LocalMachine
    .LoadImageFromUrlWithFallback("https://example.com/profile.jpg", 
                                 defaultImageBytes, 
                                 desiredWidth: 200, 
                                 desiredHeight: 200);
// Create and cache thumbnail from existing image
await CacheDatabase.LocalMachine.CreateAndCacheThumbnail(
    sourceKey: "original_photo",
    thumbnailKey: "photo_thumb", 
    thumbnailWidth: 150, 
    thumbnailHeight: 150,
    absoluteExpiration: DateTimeOffset.Now.AddDays(30));

// Load the cached thumbnail
var thumbnail = await CacheDatabase.LocalMachine.LoadImage("photo_thumb");
// Get image dimensions without fully loading
var imageSize = await CacheDatabase.LocalMachine.GetImageSize("large_image");
Console.WriteLine($"Image size: {imageSize.Width}x{imageSize.Height}");
Console.WriteLine($"Aspect ratio: {imageSize.AspectRatio:F2}");

// Use size info for layout decisions
if (imageSize.AspectRatio > 1.5)
{
    // Wide image
    SetWideImageLayout();
}
else
{
    // Square or tall image
    SetNormalImageLayout();
}
// Clear images matching a pattern
await CacheDatabase.LocalMachine.ClearImageCache(key => key.StartsWith("temp_"));

// Clear all user avatars
await CacheDatabase.UserAccount.ClearImageCache(key => key.Contains("avatar"));

// Clear expired images
await CacheDatabase.LocalMachine.ClearImageCache(key => 
    key.StartsWith("cache_") && IsExpired(key));
Complete Example: Photo Gallery App
public class PhotoGalleryService
{
    private readonly IBlobCache _imageCache;
    private readonly IBlobCache _thumbnailCache;

    public PhotoGalleryService()
    {
        // Initialize Akavache with drawing support
        CacheDatabase.Initialize(builder =>
            builder.WithApplicationName("PhotoGallery")
                   .WithSerializer(new SystemJsonSerializer())
                   .WithSqliteDefaults());

        _imageCache = CacheDatabase.LocalMachine;
        _thumbnailCache = CacheDatabase.UserAccount;
    }

    public async Task<IBitmap> LoadPhotoAsync(string photoId, bool generateThumbnail = false)
    {
        try
        {
            // Try to load from cache first
            var photo = await _imageCache.LoadImage($"photo_{photoId}");
            
            // Generate thumbnail if requested and not exists
            if (generateThumbnail)
            {
                await _thumbnailCache.CreateAndCacheThumbnail(
                    $"photo_{photoId}", 
                    $"thumb_{photoId}", 
                    200, 200,
                    DateTimeOffset.Now.AddMonths(1));
            }
            
            return photo;
        }
        catch (KeyNotFoundException)
        {
            // Load from remote URL if not cached
            var photoUrl = $"https://api.photos.com/images/{photoId}";
            return await _imageCache.LoadImageFromUrl($"photo_{photoId}", photoUrl, 
                absoluteExpiration: DateTimeOffset.Now.AddDays(7));
        }
    }

    public async Task<IBitmap> LoadThumbnailAsync(string photoId)
    {
        try
        {
            return await _thumbnailCache.LoadImage($"thumb_{photoId}", 200, 200);
        }
        catch (KeyNotFoundException)
        {
            // Generate thumbnail from full image
            var fullImage = await LoadPhotoAsync(photoId);
            await _thumbnailCache.SaveImage($"thumb_{photoId}", fullImage, 
                DateTimeOffset.Now.AddMonths(1));
            return await _thumbnailCache.LoadImage($"thumb_{photoId}", 200, 200);
        }
    }

    public async Task PreloadGalleryAsync(IEnumerable<string> photoIds)
    {
        var photoUrls = photoIds.Select(id => $"https://api.photos.com/images/{id}");
        await _imageCache.PreloadImagesFromUrls(photoUrls, 
            DateTimeOffset.Now.AddDays(7));
    }

    public async Task ClearOldCacheAsync()
    {
        // Clear images older than 30 days
        await _imageCache.ClearImageCache(key => 
            key.StartsWith("photo_") && IsOlderThan30Days(key));
        
        // Clear thumbnails older than 60 days  
        await _thumbnailCache.ClearImageCache(key => 
            key.StartsWith("thumb_") && IsOlderThan60Days(key));
    }

    private static bool IsOlderThan30Days(string key) => 
        /* Implementation to check cache age */ false;
        
    private static bool IsOlderThan60Days(string key) => 
        /* Implementation to check cache age */ false;
}

Akavache.Settings provides a specialized settings database for installable applications. It creates persistent settings that are stored one level down from the application folder, making application updates less painful as the settings survive reinstalls.

<PackageReference Include="Akavache.Settings" Version="11.0.1" />
1. Create a Settings Class
using Akavache.Settings;

public class AppSettings : SettingsBase
{
    public AppSettings() : base(nameof(AppSettings))
    {
    }

    // Boolean setting with default value
    public bool EnableNotifications
    {
        get => GetOrCreate(true);
        set => SetOrCreate(value);
    }

    // String setting with default value
    public string UserName
    {
        get => GetOrCreate("DefaultUser");
        set => SetOrCreate(value);
    }

    // Numeric settings
    public int MaxRetries
    {
        get => GetOrCreate(3);
        set => SetOrCreate(value);
    }

    public double CacheTimeout
    {
        get => GetOrCreate(30.0);
        set => SetOrCreate(value);
    }

    // Enum setting
    public LogLevel LoggingLevel
    {
        get => GetOrCreate(LogLevel.Information);
        set => SetOrCreate(value);
    }
}

public enum LogLevel
{
    Debug,
    Information,
    Warning,
    Error
}
2. Initialize Settings Store
using Akavache.Core;
using Akavache.SystemTextJson;
using Akavache.Settings;

// Initialize Akavache with settings support
var appSettings = default(AppSettings);

CacheDatabase.Initialize(builder =>
    builder.WithApplicationName("MyApp")
           .WithSerializer(new SystemJsonSerializer())
           .WithSettingsStore<AppSettings>(settings => appSettings = settings));

// Now use the settings
appSettings.EnableNotifications = false;
appSettings.UserName = "John Doe";
appSettings.MaxRetries = 5;

Console.WriteLine($"User: {appSettings.UserName}");
Console.WriteLine($"Notifications: {appSettings.EnableNotifications}");
Custom Settings Cache Path

By default, settings are stored in a subfolder of your application directory. You can customize this path:

CacheDatabase.Initialize(builder =>
    builder.WithApplicationName("MyApp")
           .WithSerializer(new SystemJsonSerializer())
           .WithSettingsCachePath(@"C:\MyApp\Settings")  // Custom path
           .WithSettingsStore<AppSettings>(settings => appSettings = settings));
Multiple Settings Classes

You can create multiple settings classes for different categories:

public class UserSettings : SettingsBase
{
    public UserSettings() : base(nameof(UserSettings)) { }
    
    public string Theme
    {
        get => GetOrCreate("Light");
        set => SetOrCreate(value);
    }
}

public class NetworkSettings : SettingsBase
{
    public NetworkSettings() : base(nameof(NetworkSettings)) { }
    
    public int TimeoutSeconds
    {
        get => GetOrCreate(30);
        set => SetOrCreate(value);
    }
}

// Initialize multiple settings
var userSettings = default(UserSettings);
var networkSettings = default(NetworkSettings);

CacheDatabase.Initialize(builder =>
    builder.WithApplicationName("MyApp")
           .WithSerializer(new SystemJsonSerializer())
           .WithSettingsStore<UserSettings>(settings => userSettings = settings)
           .WithSettingsStore<NetworkSettings>(settings => networkSettings = settings));

For sensitive settings, use encrypted storage:

public class SecureSettings : SettingsBase
{
    public SecureSettings() : base(nameof(SecureSettings)) { }
    
    public string ApiKey
    {
        get => GetOrCreate(string.Empty);
        set => SetOrCreate(value);
    }
    
    public string DatabasePassword
    {
        get => GetOrCreate(string.Empty);
        set => SetOrCreate(value);
    }
}

// Initialize with encryption
var secureSettings = default(SecureSettings);

CacheDatabase.Initialize(builder =>
    builder.WithApplicationName("MyApp")
           .WithSerializer(new SystemJsonSerializer())
           .WithSecureSettingsStore<SecureSettings>("mySecurePassword", 
               settings => secureSettings = settings));

// Use encrypted settings
secureSettings.ApiKey = "sk-1234567890abcdef";
secureSettings.DatabasePassword = "super-secret-password";

You can specify custom database names for settings:

var appSettings = default(AppSettings);

CacheDatabase.Initialize(builder =>
    builder.WithApplicationName("MyApp")
           .WithSerializer(new SystemJsonSerializer())
           .WithSettingsStore<AppSettings>(
               settings => appSettings = settings, 
               "CustomAppConfig"));  // Custom database name

Here's a comprehensive example showing all data types and features:

public class ComprehensiveSettings : SettingsBase
{
    public ComprehensiveSettings() : base(nameof(ComprehensiveSettings))
    {
    }

    // Basic types with defaults
    public bool BoolSetting
    {
        get => GetOrCreate(true);
        set => SetOrCreate(value);
    }

    public byte ByteSetting
    {
        get => GetOrCreate((byte)123);
        set => SetOrCreate(value);
    }

    public short ShortSetting
    {
        get => GetOrCreate((short)16);
        set => SetOrCreate(value);
    }

    public int IntSetting
    {
        get => GetOrCreate(42);
        set => SetOrCreate(value);
    }

    public long LongSetting
    {
        get => GetOrCreate(123456L);
        set => SetOrCreate(value);
    }

    public float FloatSetting
    {
        get => GetOrCreate(2.5f);
        set => SetOrCreate(value);
    }

    public double DoubleSetting
    {
        get => GetOrCreate(3.14159);
        set => SetOrCreate(value);
    }

    public string StringSetting
    {
        get => GetOrCreate("Default Value");
        set => SetOrCreate(value);
    }

    // Nullable types
    public string? NullableStringSetting
    {
        get => GetOrCreate<string?>(null);
        set => SetOrCreate(value);
    }

    // Complex types (automatically serialized)
    public List<string> StringListSetting
    {
        get => GetOrCreate(new List<string> { "Item1", "Item2" });
        set => SetOrCreate(value);
    }

    public Dictionary<string, int> DictionarySetting
    {
        get => GetOrCreate(new Dictionary<string, int> { ["Key1"] = 1, ["Key2"] = 2 });
        set => SetOrCreate(value);
    }

    // Custom objects
    public WindowPosition WindowPosition
    {
        get => GetOrCreate(new WindowPosition { X = 100, Y = 100, Width = 800, Height = 600 });
        set => SetOrCreate(value);
    }
}

public class WindowPosition
{
    public int X { get; set; }
    public int Y { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }
}

// Usage
var settings = default(ComprehensiveSettings);
CacheDatabase.Initialize(builder =>
    builder.WithApplicationName("MyApp")
           .WithSerializer(new SystemJsonSerializer())
           .WithSettingsStore<ComprehensiveSettings>(s => settings = s));

// Use the settings
settings.StringListSetting.Add("Item3");
settings.WindowPosition = new WindowPosition { X = 200, Y = 150, Width = 1024, Height = 768 };
settings.DictionarySetting["NewKey"] = 999;
Settings Lifecycle Management Cleanup on Application Exit
// In your application shutdown code
public async Task OnApplicationExit()
{
    var builder = CacheDatabase.Builder;
    
    // Dispose settings stores to ensure data is flushed
    await builder.DisposeSettingsStore<AppSettings>();
    await builder.DisposeSettingsStore<UserSettings>();
    
    // Regular Akavache shutdown
    await CacheDatabase.Shutdown();
}
Delete Settings (Reset to Defaults)
// Delete a specific settings store
var builder = CacheDatabase.Builder;
await builder.DeleteSettingsStore<AppSettings>();

// Settings will be recreated with default values on next access
var builder = CacheDatabase.Builder;
var existingSettings = builder.GetSettingsStore<AppSettings>();

if (existingSettings != null)
{
    Console.WriteLine("Settings already exist");
}
else
{
    Console.WriteLine("First run - settings will be created with defaults");
}
// In MauiProgram.cs
public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder.UseMauiApp<App>();

        // Initialize Akavache early
        CacheDatabase.Serializer = new SystemJsonSerializer();
        CacheDatabase.ForcedDateTimeKind = DateTimeKind.Utc;
        
        CacheDatabase.Initialize(cacheBuilder =>
            cacheBuilder.WithApplicationName("MyMauiApp")
                       .WithSqliteDefaults());

        return builder.Build();
    }
}
// In App.xaml.cs
public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        ConfigureAkavache();
        base.OnStartup(e);
    }

    protected override void OnExit(ExitEventArgs e)
    {
        // Important: Shutdown Akavache properly
        CacheDatabase.Shutdown().Wait();
        base.OnExit(e);
    }

    private static void ConfigureAkavache()
    {
        CacheDatabase.Serializer = new SystemJsonSerializer();
        CacheDatabase.ForcedDateTimeKind = DateTimeKind.Utc;

        CacheDatabase.Initialize(builder =>
            builder.WithApplicationName("MyWpfApp")
                   .WithSqliteDefaults());
    }
}
// In AppDelegate.cs or SceneDelegate.cs
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
    CacheDatabase.Serializer = new SystemJsonSerializer();
    CacheDatabase.Initialize(builder =>
        builder.WithApplicationName("MyiOSApp")
               .WithSqliteDefaults());

    return base.FinishedLaunching(application, launchOptions);
}
// In MainActivity.cs or Application class
protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);

    CacheDatabase.Serializer = new SystemJsonSerializer();
    CacheDatabase.Initialize(builder =>
        builder.WithApplicationName("MyAndroidApp")
               .WithSqliteDefaults());
}
// In App.xaml.cs
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
    CacheDatabase.Serializer = new SystemJsonSerializer();
    CacheDatabase.Initialize(builder =>
        builder.WithApplicationName("MyUwpApp")
               .WithSqliteDefaults());

    // Rest of initialization...
}

Important for UWP: Mark your application as x86 or ARM, not Any CPU.

Performance comparison of different serializers (operations per second):

Operation System.Text.Json Newtonsoft.Json BSON Serialize small object 50,000 25,000 20,000 Deserialize small object 45,000 22,000 18,000 Serialize large object 5,000 2,500 2,000 Deserialize large object 4,500 2,200 1,800

For comprehensive performance analysis and V10 vs V11 comparison:

// 1. Use System.Text.Json for best performance
CacheDatabase.Serializer = new SystemJsonSerializer();

// 2. Use batch operations for multiple items
await CacheDatabase.UserAccount.InsertObjects(manyItems);

// 3. Set appropriate expiration times
await CacheDatabase.LocalMachine.InsertObject("temp", data, 30.Minutes().FromNow());

// 4. Use InMemory cache for frequently accessed data
await CacheDatabase.InMemory.InsertObject("hot_data", frequentData);

// 5. Avoid storing very large objects
// Instead, break them into smaller chunks or use compression

// 6. Use specific types instead of object when possible
await CacheDatabase.UserAccount.GetObject<SpecificType>("key"); // Good
await CacheDatabase.UserAccount.Get("key", typeof(SpecificType)); // Slower
// โœ… Do: Initialize once at app startup
public class App
{
    static App()
    {
        CacheDatabase.Serializer = new SystemJsonSerializer();
        CacheDatabase.Initialize(builder =>
            builder.WithApplicationName("MyApp")
                   .WithSqliteDefaults());
    }
}

// โŒ Don't: Initialize multiple times
// โœ… Do: Use consistent, descriptive key naming
await CacheDatabase.UserAccount.InsertObject("user_profile_123", userProfile);
await CacheDatabase.LocalMachine.InsertObject("api_cache_weather_seattle", weatherData);

// โœ… Do: Use constants for keys
public static class CacheKeys
{
    public const string UserProfile = "user_profile";
    public const string WeatherData = "weather_data";
}

// โŒ Don't: Use random or inconsistent keys
await CacheDatabase.UserAccount.InsertObject("xyz123", someData);
// โœ… Do: Handle KeyNotFoundException appropriately
try
{
    var data = await CacheDatabase.UserAccount.GetObject<MyData>("key");
}
catch (KeyNotFoundException)
{
    // Provide fallback or default behavior
    var defaultData = new MyData();
}

// โœ… Do: Use GetOrFetchObject for remote data
var data = await CacheDatabase.LocalMachine.GetOrFetchObject("api_data",
    () => httpClient.GetFromJsonAsync<ApiData>("https://api.example.com/data"));
// โœ… Do: Use appropriate cache types
await CacheDatabase.UserAccount.InsertObject("user_settings", settings);     // Persistent user data
await CacheDatabase.LocalMachine.InsertObject("api_cache", apiData);         // Cacheable data
await CacheDatabase.Secure.InsertObject("api_key", apiKey);                  // Sensitive data
await CacheDatabase.InMemory.InsertObject("session_data", sessionData);      // Temporary data
// โœ… Do: Set appropriate expiration times
await CacheDatabase.LocalMachine.InsertObject("api_data", data, 1.Hours().FromNow());
await CacheDatabase.LocalMachine.InsertObject("image_cache", imageBytes, 1.Days().FromNow());

// โœ… Do: Don't expire user settings (unless necessary)
await CacheDatabase.UserAccount.InsertObject("user_preferences", prefs); // No expiration
// โœ… Do: Always shutdown Akavache properly
public override void OnExit(ExitEventArgs e)
{
    CacheDatabase.Shutdown().Wait();
    base.OnExit(e);
}

// For MAUI/Xamarin apps
protected override void OnSleep()
{
    CacheDatabase.Shutdown().Wait();
    base.OnSleep();
}
// โœ… Do: Use in-memory cache for unit tests
[SetUp]
public void Setup()
{
    CacheDatabase.Serializer = new SystemJsonSerializer();
    CacheDatabase.Initialize(builder =>
        builder.WithApplicationName("TestApp")
               .WithInMemoryDefaults());
}

[TearDown]
public void TearDown()
{
    CacheDatabase.Shutdown().Wait();
}
1. "No serializer has been registered"
// Fix: Register a serializer before initializing
CacheDatabase.Serializer = new SystemJsonSerializer();
CacheDatabase.Initialize(/* ... */);
2. "BlobCache has not been initialized"
// Fix: Call Initialize before using cache
CacheDatabase.Initialize(builder => builder.WithApplicationName("MyApp").WithInMemoryDefaults());
var data = await CacheDatabase.UserAccount.GetObject<MyData>("key");
3. Data compatibility issues
// Fix: Use cross-compatible serializer or migration
CacheDatabase.Serializer = new NewtonsoftBsonSerializer(); // Most compatible
4. SQLite errors on mobile
// Fix: Ensure SQLitePCL.raw bundle is installed
// Add to your project:
// <PackageReference Include="SQLitePCLRaw.lib.e_sqlite3" Version="2.1.11" />
// If using Encrypted SQLite, also add:
// <PackageReference Include="SQLitePCLRaw.lib.e_sqlcipher" Version="2.1.11" />
// Add LinkerPreserve.cs to your iOS project:
public static class LinkerPreserve
{
    static LinkerPreserve()
    {
        var persistentName = typeof(SQLitePersistentBlobCache).FullName;
        var encryptedName = typeof(SQLiteEncryptedBlobCache).FullName;
    }
}

Ensure your UWP project targets a specific platform (x86, x64, ARM) rather than "Any CPU".

Akavache is licensed under the MIT License.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4