eeCLOUD 4.1.0

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

eeCLOUD

eeCLOUD is a .NET data engine built around a high-performance logical storage model.

It is designed for teams that want:

  • a very fast persistence layer
  • a schema-flexible model
  • automatic database and table bootstrap
  • simple APIs for structured and semi-structured data

eeCLOUD is not a traditional ORM. It does not start from an entity-to-table relational model. Instead, it works through its own logical concepts such as Application, Memory, MemoryArea, Address, Index, ID, Reference, date and create.

At its core, eeCLOUD is optimized for productivity first, while still keeping a strong focus on real-world performance.


Installation

dotnet add package eeCLOUD

Requirements:

  • .NET 8.0 or later

Quick Start

using eeCLOUD;

var config = new Config
{
    server = "127.0.0.1:5432",
    username = "postgres",
    password = "your-password",
    type = ServerType.PostgreSQL
};

var db = new Application(config);

await db.WriteData("myapp", "users", "user_001", new
{
    email = "hello@example.com",
    role = "admin",
    enabled = true
});

Memory user = await db.ReadData("myapp", "users", "user_001");

Databases and tables are created automatically when needed.


Core Concepts

Application

An Application is the top logical container. On SQL backends it typically maps to a database.

Memory

A Memory is the logical equivalent of a table or collection. It is the main addressable storage space in eeCLOUD.

MemoryArea

A MemoryArea is a single stored record inside a Memory.

Address

  • Type: long
  • unique
  • monotonic
  • primary physical identifier

The address is the closest concept to a physical storage address.

Index

  • Type: string
  • unique logical identifier
  • commonly a GUID

Useful for external integration, semantic lookup and stable identifiers.

ID

  • Type: string
  • not unique
  • indexed

Useful for grouping, partitioning and NoSQL-style queries.

Reference

  • Type: long
  • points to the address of another record

Useful when you want fast direct links between memories.

date vs create

  • date: business or logical date
  • create: actual persistence timestamp

date is especially important for range queries and time-based data access.


Storage Paradigms

eeCLOUD currently supports two complementary paradigms.

1. Raw JSON Paradigm

This is the original high-performance eeCLOUD model. The whole object is stored as JSON in a single MemoryArea.

await db.WriteData("myapp", "users", "user_001", new
{
    email = "hello@example.com",
    profile = new
    {
        displayName = "Giovanni",
        theme = "dark"
    }
});

Best for:

  • transaction-heavy flows
  • hot paths
  • maximum write/read throughput
  • simple and compact storage

2. Object Graph Paradigm (V4)

With the new object paradigm, nested objects can be persisted as dedicated child memories.

The parent record stores only GUID references to child objects, and eeCLOUD reconstructs the full graph automatically during read.

public class Account
{
    public long id { get; set; }
    public string email { get; set; } = "";
    public string password { get; set; } = "";
    public bool enabled { get; set; } = true;
    public bool terms { get; set; }
    public ClientConnectionInfo registrationInfo { get; set; } = new();
    public DateTime registrationDate { get; set; }
    public ClientConnectionInfo connectionInfo { get; set; } = new();
}

Example write:

await db.WriteObjectData("myapp", "accounts", "acc_001", account);

Conceptually, the parent memory stores something like:

{
  "id": 1,
  "email": "hello@example.com",
  "password": "secret",
  "enabled": true,
  "terms": true,
  "registrationInfo": "guid-child-1",
  "registrationDate": "2026-04-24T18:00:00Z",
  "connectionInfo": "guid-child-2"
}

And the children are saved in dedicated memories such as:

accounts§registrationinfo
accounts§connectioninfo

Best for:

  • user profiles
  • dashboard-managed settings
  • rich configuration objects
  • models that evolve over time
  • gradual refactors of old projects

Current SQL engine support for the V4 Object Graph fast path:

  • PostgreSQL
  • MySQL
  • SQL Server

Additional notes:

  • eeCACHE supports the same Object Graph APIs with its own backend semantics.
  • FTP does not support Object Graph persistence.
  • SFTP does not support Object Graph persistence.

Raw JSON vs Object Graph

Use WriteData / ReadData when:

  • you want the fastest path
  • nested objects do not need to be separated
  • you prefer a single JSON payload

Use WriteObjectData / ReadObjectData when:

  • nested objects should live in dedicated child memories
  • you want a more modular storage model
  • your object graph grows over time
  • readability and maintainability matter more than raw peak throughput

In general:

  • Raw JSON remains the best fit for high-throughput transactional flows
  • object graph is ideal for structured configuration-style data
  • the optimized SQL Object Graph write path now uses a batched persistence flow, which keeps warm write performance close to the Raw JSON path

Write APIs

Raw JSON write

await db.WriteData("myapp", "orders", "ord_001", new
{
    number = "2026-0001",
    total = 129.90m
});

Object write

await db.WriteObjectData("myapp", "accounts", "acc_001", account);

There are also overloads with:

  • explicit index
  • explicit date
  • reference
  • clusterized: true

Read APIs

Raw JSON read

Memory data = await db.ReadData("myapp", "orders", "ord_001");
Memory list = await db.ReadAllData("myapp", "orders");

Object read

ObjectMemory<Account> accountData =
    await db.ReadObjectData<Account>("myapp", "accounts", "acc_001");

Read by latest record:

ObjectMemory<Account> lastAccount =
    await db.ReadObjectData<Account>("myapp", "accounts");

Read by index:

ObjectMemory<Account> indexed =
    await db.ReadObjectIndexData<Account>("myapp", "accounts", "some-index");

ReadAllObjectData

ReadAllObjectData<T> returns:

  • the raw Memory
  • the rebuilt typed list List<T>
ObjectMemories<Account> allAccounts =
    await db.ReadAllObjectData<Account>("myapp", "accounts");

Range query:

ObjectMemories<Account> accountsInRange =
    await db.ReadAllObjectData<Account>(
        "myapp",
        "accounts",
        DateTime.UtcNow.AddDays(-7),
        DateTime.UtcNow,
        Order.ASC);

Field filter:

ObjectMemories<Account> enabledAccounts =
    await db.ReadAllObjectData<Account>(
        "myapp",
        "accounts",
        "email",
        "hello@example.com");

The ReadAllObjectData<T> overloads mirror the Raw JSON ReadAllData(...) patterns for:

  • full reads
  • reference
  • id
  • field/value
  • date ranges
  • paging

Update APIs

Raw JSON update

await db.UpdateData("myapp", "orders", address, new
{
    number = "2026-0001",
    total = 149.90m
});

Object update

await db.UpdateObjectData("myapp", "accounts", address, account);

Object update semantics:

  • current child objects in the new payload are rewritten
  • missing child memories are created automatically when needed
  • the parent is updated with the new GUID references
  • existing Raw JSON rows can be converted in-place to Object Graph rows through UpdateObjectData(...)
  • removed children are no longer referenced
  • old child rows are not automatically deleted

On PostgreSQL, MySQL and SQL Server, the Object Graph update path now batches child persistence before updating the parent row, so updates no longer degrade into one write round-trip per nested child.

This makes updates safer and predictable, especially in configuration-oriented scenarios.


Mixed Raw JSON/V4 Mode

eeCLOUD supports gradual migration of existing memories.

This means the same memory can contain:

  • existing Raw JSON rows with nested inline JSON
  • new V4 rows with GUID references to child memories

To enable mixed compatibility during object reads:

ObjectMemory<Account> accountData =
    await db.ReadObjectData<Account>(
        "myapp",
        "accounts",
        "acc_001",
        mixed: true);

Use mixed: true when:

  • you are refactoring old projects
  • the memory already contains Raw JSON rows
  • you want to migrate gradually instead of renaming tables

Default behavior is mixed: false, which keeps the standard V4 optimized path.


Schema Evolution

The object graph model supports progressive schema evolution.

If a new child object is added in the future:

  • old rows remain readable
  • missing child objects are returned as null / default values
  • the new child memory is created only when a record actually writes that child

This makes the model practical for long-lived applications that evolve over time.


Cluster Storage

eeCLOUD supports clustered storage to improve scalability on very large memories.

Cluster creation

Clusters are created only during write operations by explicitly enabling:

clusterized: true

Example:

await db.WriteData("myapp", "orders", "ord_001", order, clusterized: true);
await db.WriteObjectData("myapp", "accounts", "acc_001", account, clusterized: true);

When clustering is enabled:

  • the logical parent memory remains stable
  • data is written to cluster memories such as orders§c_0
  • cluster resolution is calculated automatically from the address

Example:

orders
orders§c_0
orders§c_1
orders§c_2

Automatic cluster resolution on read

Reads do not need any special flag.

eeCLOUD resolves the cluster automatically, so consumers always read using the logical memory name.

For the object graph model:

  • the parent memory can be clusterized
  • child object memories remain transparent and are handled automatically

eeCACHE

eeCACHE is an optional persistent cache engine for eeCLOUD.

It is disabled by default and must be injected explicitly:

var cache = new eeCACHE();
var db = new Application(config, cache);

Architecture

eeCACHE uses two layers:

  • in-memory layer

    • very fast
    • process-local
    • supports TTL / expiration
  • persistent layer

    • local memory-mapped storage
    • survives process restart
    • can be shared across processes on the same machine

Usage modes

As primary backend:

config.type = ServerType.eeCACHE;

As local accelerator in front of a SQL backend:

  • SQL remains the source of truth
  • eeCACHE speeds up reads and writes locally

Configuration

var config = new Config
{
    server = "192.168.1.10:5432",
    username = "dbuser",
    password = "dbpassword",
    type = ServerType.PostgreSQL,
    clusterSize = 100000
};

server

  • format: host or host:port
  • if port is omitted, the backend default is used

username / password

Credentials for the selected backend engine.

The user should be allowed to create databases and tables if you want full automatic bootstrap.

clusterSize

Maximum number of records per cluster before eeCLOUD moves to the next cluster.


Supported Backends

  • PostgreSQL
  • MySQL
  • SQL Server
  • eeCACHE
  • FTP
  • SFTP

SFTP on Windows Server

SFTP is a good fit when you want a remote file backend without the operational overhead of a classic FTP/FTPS server.

Typical eeCLOUD config:

var config = new Config
{
    server = "your-server:22",
    username = "sftp-user",
    password = "your-password",
    type = ServerType.Sftp
};

Notes:

  • server supports host or host:port
  • if the port is omitted, SFTP falls back to port 22
  • the SftpEngine uses the SFTP root directory exposed to the configured user
  • on Windows Server this is typically the user's SFTP home or ChrootDirectory

Windows Server checklist

On Windows Server with OpenSSH Server:

  1. make sure sshd is running
  2. enable the inbound firewall rule for the active network profile
  3. add the SFTP user to the OpenSSH Users group
  4. optionally force internal-sftp and set a dedicated ChrootDirectory

Useful commands:

Start-Service sshd
Set-Service -Name sshd -StartupType Automatic
Set-NetFirewallRule -Name OpenSSH-Server-In-TCP -Profile Private,Public
Add-LocalGroupMember -Group "OpenSSH Users" -Member "sftp-user"
Restart-Service sshd

Example sshd_config block:

Subsystem sftp sftp-server.exe

AllowGroups administrators "openssh users"

Match User sftp-user
    ForceCommand internal-sftp
    ChrootDirectory C:\inetpub\wwwroot\CDN
    PasswordAuthentication yes
    AllowTcpForwarding no
    X11Forwarding no

With a configuration like this, eeCLOUD writes under the SFTP root seen by the user, for example:

C:\inetpub\wwwroot\CDN\<app>\<memory>\...

The SftpEngine also maintains a metadata index file for each memory:

<app>/<memory>/.eecloud.index.json

When to Use eeCLOUD

Recommended for:

  • IoT backends
  • logging and event streams
  • session and state storage
  • dashboard-driven configuration
  • semi-structured data
  • high-throughput backend services

Less suitable for:

  • complex relational SQL joins as the main workload
  • heavy analytical SQL reporting
  • classic schema-first ORM-centric architectures

Notes on Performance

eeCLOUD is designed to give you a choice.

  • the Raw JSON paradigm remains the reference path for hot transactional workloads
  • the Object Graph paradigm introduces more structure and flexibility
  • on PostgreSQL, MySQL and SQL Server, WriteObjectData(...) and UpdateObjectData(...) now use a batched Object Graph persistence flow
  • without batching, Object Graph writes and updates would scale almost linearly with the number of child and nested child objects because every branch would require separate write round-trips
  • in steady-state SQL scenarios, WriteObjectData(...) can now run very close to WriteData(...)

In practical terms:

  • use WriteData / ReadData for maximum raw performance
  • use WriteObjectData / ReadObjectData / ReadAllObjectData where a modular graph model gives you more value
  • prefer Raw JSON when the payload is compact and the hottest path is pure throughput
  • prefer Object Graph when maintainability, schema evolution and child-memory separation matter more than a fully monolithic JSON payload


Made with love by Giovanni Petruzzellis

Product Compatible and additional computed target framework versions.
.NET 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 was computed.  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
4.1.0 86 5/10/2026
4.0.1 99 5/1/2026
4.0.0 103 4/28/2026
3.3.7 107 4/9/2026
3.3.6 114 3/31/2026
3.3.5 112 3/19/2026
3.3.4 105 3/6/2026
3.3.3 141 2/3/2026
3.3.2 146 1/2/2026
3.2.0 205 11/23/2025
3.1.9 228 10/28/2025
3.1.8 222 10/21/2025
3.1.6 213 10/20/2025
3.1.5 135 10/18/2025
3.1.4 220 10/15/2025
3.1.3 220 10/13/2025
3.1.1 257 9/7/2025
3.1.0 268 9/4/2025
Loading failed

eeCLOUD 4.1.0 introduces the new SFTP backend and expands file-based engine support for remote binary storage scenarios.

Highlights in this release:
- Added `SftpEngine` as a new backend using password-based OpenSSH / SFTP connections.
- Added `ServerType.Sftp` support across the shared core engine selection flow.
- Added SFTP support for file-based write, read, count, size, update, rename, delete, restore and erase operations.
- Extended file-engine payload handling so SFTP follows the same binary write model used by FTP.
- Added package metadata and README updates for the new SFTP backend.
- Added Windows Server setup notes for OpenSSH, firewall profiles and `OpenSSH Users` membership.
- Preserved the current file-backend positioning where Object Graph persistence is not supported on FTP/SFTP.