CloudStorageORM 1.0.16
dotnet add package CloudStorageORM --version 1.0.16
NuGet\Install-Package CloudStorageORM -Version 1.0.16
<PackageReference Include="CloudStorageORM" Version="1.0.16" />
<PackageVersion Include="CloudStorageORM" Version="1.0.16" />
<PackageReference Include="CloudStorageORM" />
paket add CloudStorageORM --version 1.0.16
#r "nuget: CloudStorageORM, 1.0.16"
#:package CloudStorageORM@1.0.16
#addin nuget:?package=CloudStorageORM&version=1.0.16
#tool nuget:?package=CloudStorageORM&version=1.0.16
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.
โจ Current status
- โ
Current release line:
v1.0.16 - โ
Targets
net10.0 - โ Azure Blob Storage provider is implemented
- โ AWS S3 provider is implemented
- โ
EF-style
DbContextintegration viaUseCloudStorageOrm(...) - โ 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.16adds configurable transient-fault retries (bounded exponential backoff + jitter) at shared persistence/query execution boundaries - โ
v1.0.16completes runtime logging/tracing wiring across save/query/transaction/recovery paths - โ
v1.0.16Azure and AWS integration suites cover rollback, commit, crash-recovery, and stale-ETag conflict windows - โ
v1.0.15implements crash-safe, idempotent transaction replay with operation-level progress tracking - โ
v1.0.14preservesIf-MatchETag preconditions for staged transaction save/delete replay and surfaces conflicts asDbUpdateConcurrencyException - โ
v1.0.14enables Dependabot for NuGet and GitHub Actions updates via.github/dependabot.yml - โ
v1.0.13adds server-sideSkip/Takepushdown for supported query shapes - โ
v1.0.13refreshes 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 understorage.Azureandstorage.Aws. - Observability is optional and configured under
storage.Observability(logging, tracing, and diagnostics toggles). CloudStorageOptions.ConnectionStringwas removed; usestorage.Azure.ConnectionStringfor 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. SaveChangesduring an active transaction stages durable operations in the manifest;Commitmarks the manifest as committed and replays operations;Rollbackmarks the transaction as aborted.- Each transaction has a unique
TransactionId(Guid) and only one active transaction is allowed perDbContextinstance. - 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()(shadowETag) orUseObjectETagConcurrency(e => e.ETag)(mapped property). - Entities can optionally implement
IETagto 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-Matchconditions (Azure Blob and AWS S3) and conflicts are raised asDbUpdateConcurrencyException. - 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.
IDatabaseCreatorbehavior 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 throughILogger.EnableTracing: enables CloudStorageORMActivitySourcespans (CloudStorageORM).EnableDiagnostics: currently represented in options/debug info; customDiagnosticListenerevents 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
CI-parity local run (recommended)
./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:
- Once against EF Core InMemory
- Once against CloudStorageORM configured for Azure Blob Storage / Azurite
- 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
- Library documentation
- Observability guide
- API reference (DocFX)
- API reference landing page
- Sample app guide
- Testing with Azurite
- Testing with LocalStack
- CI workflow and artifacts
- Contributing
- Roadmap
๐ก๏ธ 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 | Versions 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. |
-
net10.0
- AWSSDK.S3 (>= 4.0.21.1)
- Azure.Storage.Blobs (>= 12.27.0)
- Microsoft.EntityFrameworkCore (>= 10.0.6)
- Microsoft.EntityFrameworkCore.Relational (>= 10.0.6)
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 |