CloudStorageORM 1.0.16

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

CloudStorageORM

Simplify persistence. Embrace scalability. Build the future.

CloudStorageORM is an Entity Framework-style provider that persists entities into cloud object storage. The current main branch targets .NET 10, uses EF Core 9, and currently ships with Azure Blob Storage and * AWS S3* providers. Support for Google Cloud Storage remains on the roadmap.

License .NET NuGet Build Status Publish Status Contributing Security Policy

๐Ÿ‘‰ See the roadmap


โœจ Current status

  • โœ… Current release line: v1.0.16
  • โœ… Targets net10.0
  • โœ… Azure Blob Storage provider is implemented
  • โœ… AWS S3 provider is implemented
  • โœ… EF-style DbContext integration via UseCloudStorageOrm(...)
  • โœ… Sample app runs the same CRUD flow against EF InMemory, Azure, and AWS
  • โœ… Unit + integration tests run locally with Azurite and LocalStack
  • โœ… Coverage collection is wired with Coverlet + ReportGenerator
  • โœ… v1.0.16 adds configurable transient-fault retries (bounded exponential backoff + jitter) at shared persistence/query execution boundaries
  • โœ… v1.0.16 completes runtime logging/tracing wiring across save/query/transaction/recovery paths
  • โœ… v1.0.16 Azure and AWS integration suites cover rollback, commit, crash-recovery, and stale-ETag conflict windows
  • โœ… v1.0.15 implements crash-safe, idempotent transaction replay with operation-level progress tracking
  • โœ… v1.0.14 preserves If-Match ETag preconditions for staged transaction save/delete replay and surfaces conflicts as DbUpdateConcurrencyException
  • โœ… v1.0.14 enables Dependabot for NuGet and GitHub Actions updates via .github/dependabot.yml
  • โœ… v1.0.13 adds server-side Skip/Take pushdown for supported query shapes
  • โœ… v1.0.13 refreshes observability guidance for logging, tracing, and diagnostics options
  • ๐Ÿšง Google Cloud Storage provider is planned

๐Ÿ“ฆ Installation

From NuGet

dotnet add package CloudStorageORM

From source (main branch)

The repository currently targets .NET 10 SDK.

git clone https://github.com/rzavalik/CloudStorageORM.git
cd CloudStorageORM
dotnet restore CloudStorageORM.sln

๐Ÿš€ Getting started

The current recommended integration pattern is to configure a regular EF Core DbContext with UseCloudStorageOrm(...).

using CloudStorageORM.Contexts;
using CloudStorageORM.Enums;
using CloudStorageORM.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
    : CloudStorageDbContext(options)
{
    public DbSet<User> Users => Set<User>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>().HasKey(x => x.Id);
        base.OnModelCreating(modelBuilder);
    }
}

var services = new ServiceCollection();

services.AddDbContext<AppDbContext>(options =>
{
    options.UseCloudStorageOrm(storage =>
    {
        storage.Provider = CloudProvider.Azure;
        storage.ContainerName = "sampleapp-container";
        storage.Azure.ConnectionString = "UseDevelopmentStorage=true";
    });
});

Then use the context with familiar EF operations and LINQ:

await using var provider = services.BuildServiceProvider();
await using var scope = provider.CreateAsyncScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();

var user = new User
{
    Id = Guid.NewGuid().ToString(),
    Name = "John Doe",
    Email = "john.doe@example.com"
};

db.Add(user);
await db.SaveChangesAsync();

var users = await db.Set<User>().ToListAsync();
var found = db.Set<User>().FirstOrDefault(x => x.Id == user.Id);

db.Remove(found!);
await db.SaveChangesAsync();

Current provider support on main: Azure Blob Storage and AWS S3.


๐Ÿงญ Important notes for the current branch

  • The base context namespace is now CloudStorageORM.Contexts.
  • Configuration uses composition on CloudStorageOptions: common fields stay on the root, while provider-specific fields are under storage.Azure and storage.Aws.
  • Observability is optional and configured under storage.Observability (logging, tracing, and diagnostics toggles).
  • CloudStorageOptions.ConnectionString was removed; use storage.Azure.ConnectionString for Azure configuration.
  • Primary-key query predicates now support direct range-aware loading for >, >=, <, and <= in addition to equality-based lookups.
  • Coding style is enforced with file-scoped namespaces (namespace X;).
  • The sample app is covered by integration tests that publish the sample (dotnet publish) and verify the published app exits successfully.
  • Integration fixtures can skip Azure/AWS scenarios when Azurite/LocalStack are unavailable.
  • CloudStorage transaction support now uses a durable transaction journal under __cloudstorageorm/tx/<transactionId>/manifest.json.
  • SaveChanges during an active transaction stages durable operations in the manifest; Commit marks the manifest as committed and replays operations; Rollback marks the transaction as aborted.
  • Each transaction has a unique TransactionId (Guid) and only one active transaction is allowed per DbContext instance.
  • On startup of a new transaction manager instance, committed manifests are replayed and finalized (Completed), while pre-commit manifests are marked as aborted (Aborted).
  • Opt-in optimistic concurrency is available through object-store ETags. Configure entities with modelBuilder.Entity<TEntity>().UseObjectETagConcurrency() (shadow ETag) or UseObjectETagConcurrency(e => e.ETag) (mapped property).
  • Entities can optionally implement IETag to expose the current ETag value after materialization and successful saves; this interface is not required.
  • When ETag concurrency is enabled, updates/deletes use provider-native If-Match conditions (Azure Blob and AWS S3) and conflicts are raised as DbUpdateConcurrencyException.
  • Transient retries are optional and configured under storage.Retry (Enabled, MaxRetries, BaseDelay, MaxDelay, JitterFactor).
  • Future versions may add provider-native temporary locking (for example, Azure blob leases and AWS conditional/object-lock strategies) to improve concurrent-writer coordination.
  • IDatabaseCreator behavior is still minimal right now: schema-style database lifecycle methods are not fully implemented because object storage does not map 1:1 to relational database creation semantics.

Optional observability configuration

services.AddDbContext<AppDbContext>(options =>
{
    options.UseCloudStorageOrm(storage =>
    {
        storage.Provider = CloudProvider.Azure;
        storage.ContainerName = "sampleapp-container";
        storage.Azure.ConnectionString = "UseDevelopmentStorage=true";

        // Keep defaults (all true) or disable selectively.
        storage.Observability.EnableLogging = true;
        storage.Observability.EnableTracing = true;
        storage.Observability.EnableDiagnostics = true;
    });
});

What each toggle does on the current branch:

  • EnableLogging: enables CloudStorageORM log events through ILogger.
  • EnableTracing: enables CloudStorageORM ActivitySource spans (CloudStorageORM).
  • EnableDiagnostics: currently represented in options/debug info; custom DiagnosticListener events are not yet emitted.

If you only need tracing:

storage.Observability.EnableLogging = false;
storage.Observability.EnableTracing = true;
storage.Observability.EnableDiagnostics = false;

For full details and consumption examples, see docs/observability.md.


๐Ÿงช Running tests locally

./scripts/run-local-ci-tests.sh

This script mirrors CI by starting Azurite and LocalStack, then running restore, build, and tests with TRX and coverage collection.

Start Azurite (Azure integration)

docker rm -f azurite || true
docker run -d \
  -p 10000:10000 \
  -p 10001:10001 \
  -p 10002:10002 \
  --name azurite \
  mcr.microsoft.com/azure-storage/azurite:latest \
  azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0 --skipApiVersionCheck

Run the solution tests

dotnet test CloudStorageORM.sln --nologo -v minimal

Start LocalStack (AWS integration)

docker rm -f localstack || true
docker run -d \
  -p 4566:4566 \
  --name localstack \
  -e SERVICES=s3 \
  -e AWS_DEFAULT_REGION=us-east-1 \
  localstack/localstack:3

Optional AWS environment overrides

The integration fixture uses defaults, but you can override them explicitly:

export CLOUDSTORAGEORM_AWS_SERVICE_URL=http://127.0.0.1:4566
export CLOUDSTORAGEORM_AWS_ACCESS_KEY_ID=test
export CLOUDSTORAGEORM_AWS_SECRET_ACCESS_KEY=test
export CLOUDSTORAGEORM_AWS_REGION=us-east-1
export CLOUDSTORAGEORM_AWS_BUCKET=cloudstorageorm-integration-tests

Collect coverage

dotnet test CloudStorageORM.sln --nologo --settings coverlet.runsettings --collect:"XPlat Code Coverage" -v minimal
dotnet tool restore
dotnet tool run reportgenerator \
  -reports:"tests/**/TestResults/*/coverage.cobertura.xml" \
  -targetdir:"coverage/report" \
  -reporttypes:"Html"

The HTML report is generated at coverage/report/index.html.

For CI-equivalent behavior (per-test-project TRX and coverage artifacts), see docs/ci.md.


๐Ÿงช Running the sample app

dotnet run --project samples/CloudStorageORM.SampleApp/SampleApp.csproj

The app runs the same CRUD flow three times:

  1. Once against EF Core InMemory
  2. Once against CloudStorageORM configured for Azure Blob Storage / Azurite
  3. Once against CloudStorageORM configured for AWS S3 / LocalStack

For CloudStorageORM runs, the sample also executes a transaction scenario:

  • add entity inside a transaction and Rollback (entity should not persist)
  • add entity inside a transaction and Commit (entity should persist)

See docs/sampleapp.md for details.


๐Ÿ“š Documentation


๐Ÿ›ก๏ธ License

This project is licensed under the GNU General Public License v3.0 (GPL-3.0-or-later). See LICENSE for details.


๐Ÿค Contributing

Contributions are welcome. Please read CONTRIBUTING.md before opening a PR.


CloudStorageORM aims to make cloud object storage feel familiar to EF-oriented .NET applications, while staying explicit about the current provider and platform limits.

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

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.16 111 4/16/2026
1.0.15 119 4/16/2026
1.0.14 113 4/15/2026
1.0.13 109 4/15/2026
1.0.12 114 4/11/2026
1.0.11 126 4/6/2026
1.0.10 123 3/31/2026
1.0.9 116 3/20/2026
1.0.8 116 3/13/2026
1.0.7 224 5/9/2025
1.0.6 275 4/28/2025
1.0.5 257 4/28/2025
0.1.4-beta 266 4/27/2025
0.1.3-beta 253 4/27/2025
0.1.2-beta 237 4/27/2025
0.1.1-beta 230 4/27/2025
0.1.0 284 4/27/2025
0.1.0-beta 267 4/27/2025