CrystalData 0.47.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package CrystalData --version 0.47.0
                    
NuGet\Install-Package CrystalData -Version 0.47.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="CrystalData" Version="0.47.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CrystalData" Version="0.47.0" />
                    
Directory.Packages.props
<PackageReference Include="CrystalData" />
                    
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 CrystalData --version 0.47.0
                    
#r "nuget: CrystalData, 0.47.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.
#:package CrystalData@0.47.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=CrystalData&version=0.47.0
                    
Install as a Cake Addin
#tool nuget:?package=CrystalData&version=0.47.0
                    
Install as a Cake Tool

CrystalData

NuGet Build and Test

CrystalData is a persistence engine for .NET. It combines snapshot files, optional journals, backups, and independently loaded storage nodes with Tinyhand serialization and ValueLink collections.

Contents

Requirements

  • .NET 10 SDK or later

Installation

dotnet add package CrystalData

Package Manager Console:

Install-Package CrystalData

Quick start

Define a Tinyhand-serializable data type:

using System.ComponentModel;
using Tinyhand;

[TinyhandObject]
public partial class FirstData
{
    [Key(0)]
    public int Id { get; set; }

    [Key(1)]
    [DefaultValue("Hoge")]
    public string Name { get; set; } = string.Empty;
}

Register the crystal, prepare the storage services, update the data, and shut down cleanly:

using CrystalData;
using Microsoft.Extensions.DependencyInjection;

var product = new CrystalUnit.Builder()
    .ConfigureCrystal(context =>
    {
        context.AddCrystal<FirstData>(
            new CrystalConfiguration(
                new LocalFileConfiguration("Local/FirstData.tinyhand"))
            {
                SaveFormat = SaveFormat.Utf8,
                NumberOfFileHistories = 1,
            });
    })
    .Build();

var services = product.Context.ServiceProvider;
var control = services.GetRequiredService<CrystalControl>();
var result = await control.PrepareAndLoad(useQuery: false);
if (result.IsFailure())
{
    throw new InvalidOperationException($"CrystalData initialization failed: {result}");
}

var data = services.GetRequiredData<FirstData>();
data.Id++;
data.Name = "Updated";

await control.StoreAndRip();

StoreAndRip is terminal: the CrystalControl instance cannot be used after it completes. Call it during application shutdown.

NativeAOT

CrystalData supports NativeAOT. Data types must use Tinyhand source generation and be registered through the generic AddCrystal<TData>, CreateCrystal<TData>, or GetOrCreateCrystal<TData> APIs so their closed generic forms are visible at build time.

Publish an application for a specific runtime identifier:

dotnet publish -c Release -r win-x64 --self-contained -p:PublishAot=true

The CrystalData project enables the .NET AOT and trimming compatibility analyzers, and CI publishes and runs QuickStart as a native executable.

Configuration

Each registered type has a CrystalConfiguration.

Property Purpose
SaveFormat Selects binary or UTF-8 Tinyhand output. The default comes from CrystalOptions.DefaultSaveFormat.
Volatile Keeps the crystal in memory without writing snapshot files.
SaveInterval Sets the automatic snapshot interval for the crystal.
NumberOfFileHistories Sets the number of retained snapshot files. Use 0 to disable file histories.
FileConfiguration Selects the primary snapshot file.
BackupFileConfiguration Selects an optional backup snapshot file.
StorageConfiguration Configures independently loaded StoragePoint<T> data.
RequiredForLoading Passes failures for previously stored data to the recovery query.

Global defaults and limits are configured with CrystalOptions:

context.SetCrystalOptions(new CrystalOptions
{
    GlobalDirectory = new LocalDirectoryConfiguration("Data"),
    DefaultBackup = new LocalDirectoryConfiguration("Backup"),
    DefaultSaveFormat = SaveFormat.Binary,
    MemoryUsageLimit = 512L * 1024 * 1024,
});

Register more than one crystal when an application has independently persisted data sets:

context.AddCrystal<FirstData>(
    new CrystalConfiguration(new GlobalFileConfiguration("First.tinyhand")));
context.AddCrystal<SecondData>(
    new CrystalConfiguration(new GlobalFileConfiguration("Second.tinyhand")));

Crystals can also be created at runtime with CreateCrystal<TData> or retrieved or created with GetOrCreateCrystal<TData>.

Paths and backups

  • LocalFileConfiguration and LocalDirectoryConfiguration use absolute paths as-is. Relative paths are resolved against CrystalOptions.DataDirectory.
  • GlobalFileConfiguration and GlobalDirectoryConfiguration are resolved relative to CrystalOptions.GlobalDirectory.
  • EmptyFileConfiguration and EmptyDirectoryConfiguration disable the corresponding file or directory.
  • S3FileConfiguration and S3DirectoryConfiguration identify objects in an S3 bucket.

Set BackupFileConfiguration for one crystal, or set CrystalOptions.DefaultBackup to derive backup locations for crystals, journals, and auxiliary storage that do not define one explicitly.

Snapshot histories provide recovery candidates when the current file is missing or invalid. Journaling requires at least one history file for every journaled crystal.

Saving and shutdown

Use the lifecycle method that matches the operation:

Method Behavior
PrepareAndLoad() Prepares persistence services and loads registered crystals.
Store() Persists all managed crystals and auxiliary storage.
StoreAndRelease() Persists all managed data and attempts to release its resources.
StoreAndRip() Persists all managed data, records a clean shutdown, and terminates services.

For a single crystal, call ICrystal.StoreData(). For independently loaded nodes, call StoragePoint<T>.AddToSaveQueue() to schedule persistence or StoragePoint<T>.StoreData() to request it directly.

Journaling

Journaling records changes to Tinyhand structural objects between snapshots. Configure a journal and use [TinyhandObject(Structural = true)] on journaled data:

[TinyhandObject(Structural = true)]
public partial class JournalData
{
    [Key(0)]
    public partial int Count { get; set; }
}

var product = new CrystalUnit.Builder()
    .ConfigureCrystal(context =>
    {
        context.SetJournal(
            new SimpleJournalConfiguration(
                new LocalDirectoryConfiguration("Data/Journal")));

        context.AddCrystal<JournalData>(
            new CrystalConfiguration(
                new LocalFileConfiguration("Data/JournalData.tinyhand"))
            {
                NumberOfFileHistories = 3,
            });
    })
    .Build();

Structural members must be compatible with Tinyhand's structural serialization rules. ValueLink collections can also be used as journaled roots.

Auxiliary storage

StoragePoint<T> keeps a child object in an independently loaded file. Configure auxiliary storage on the owning crystal:

context.AddCrystal<RootData>(
    new CrystalConfiguration(new LocalFileConfiguration("Data/Root.tinyhand"))
    {
        StorageConfiguration = new SimpleStorageConfiguration(
            new LocalDirectoryConfiguration("Data/Storage"))
        {
            NumberOfHistoryFiles = 3,
        },
    });

The type containing a storage point must be a Tinyhand structural object. StoragePoint<T> reserves Tinyhand key 0; derived storage-point types must start their own keys at 1.

Read with TryGet. Use TryLock whenever data will be changed, and dispose the returned DataScope<T> to release the lock:

using var scope = await root.Child.TryLock(AcquisitionMode.GetOrCreate);
if (scope.IsValid)
{
    scope.Data.Count++;
}

Avoid replacing a storage-point instance with Set unless instance replacement is specifically required.

S3 storage

Supply bucket credentials through IStorageKey, then use an S3 file or directory configuration:

var storageKey = services.GetRequiredService<IStorageKey>();
storageKey.AddKey(
    "my-bucket",
    new AccessKeyPair("ACCESS_KEY_ID", "SECRET_ACCESS_KEY"));

var configuration = new CrystalConfiguration(
    new S3FileConfiguration("my-bucket", "app/FirstData.tinyhand"));

Do not embed production credentials in source code. Provide them through the application's secret-management mechanism.

Recovery

PrepareAndLoad(useQuery: true) consults the registered ICrystalDataQuery when recovery requires a decision. Pass false for non-interactive startup behavior. The second argument, loadCrystals, can defer loading registered crystals while still preparing persistence services.

CrystalData checks the primary snapshot, available histories, and configured backups. For previously stored data with RequiredForLoading = true, a load failure is passed to ICrystalDataQuery; initialization fails when the query chooses to abort.

Samples

  • QuickStart contains the smallest complete application.
  • Advanced covers backups, dynamic configuration, journals, paths, dependency injection, save timing, and storage points.

License

CrystalData is licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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 (1)

Showing the top 1 NuGet packages that depend on CrystalData:

Package Downloads
Lp

Lp is an experimental program that create value.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.48.0 47 9/7/2026
0.47.0 65 9/4/2026
0.46.2 71 9/1/2026
0.46.1 100 8/21/2026
0.46.0 105 8/20/2026
0.45.4 175 5/14/2026
0.45.3 165 5/11/2026
0.45.2 136 5/10/2026
0.45.0 131 5/8/2026
0.44.0 160 4/23/2026
0.43.1 130 4/23/2026
0.43.0 124 4/22/2026
0.42.3 138 4/16/2026
0.42.2 139 4/7/2026
0.42.1 128 4/7/2026
0.42.0 132 4/6/2026
0.41.1 138 4/6/2026
0.41.0 140 4/5/2026
0.40.0 131 4/3/2026
0.39.3 140 3/31/2026
Loading failed