Rystem.RepositoryFramework.Infrastructure.Azure.Storage.Blob
10.0.7
dotnet add package Rystem.RepositoryFramework.Infrastructure.Azure.Storage.Blob --version 10.0.7
NuGet\Install-Package Rystem.RepositoryFramework.Infrastructure.Azure.Storage.Blob -Version 10.0.7
<PackageReference Include="Rystem.RepositoryFramework.Infrastructure.Azure.Storage.Blob" Version="10.0.7" />
<PackageVersion Include="Rystem.RepositoryFramework.Infrastructure.Azure.Storage.Blob" Version="10.0.7" />
<PackageReference Include="Rystem.RepositoryFramework.Infrastructure.Azure.Storage.Blob" />
paket add Rystem.RepositoryFramework.Infrastructure.Azure.Storage.Blob --version 10.0.7
#r "nuget: Rystem.RepositoryFramework.Infrastructure.Azure.Storage.Blob, 10.0.7"
#:package Rystem.RepositoryFramework.Infrastructure.Azure.Storage.Blob@10.0.7
#addin nuget:?package=Rystem.RepositoryFramework.Infrastructure.Azure.Storage.Blob&version=10.0.7
#tool nuget:?package=Rystem.RepositoryFramework.Infrastructure.Azure.Storage.Blob&version=10.0.7
Rystem.RepositoryFramework.Infrastructure.Azure.Storage.Blob
Rystem.RepositoryFramework.Infrastructure.Azure.Storage.Blob adds an Azure Blob Storage adapter for Repository Framework.
It stores one blob per repository entity and serializes the payload as Entity<T, TKey>, not as raw T.
This package is simple and flexible for key-based storage, but list queries are mostly client-side.
Installation
dotnet add package Rystem.RepositoryFramework.Infrastructure.Azure.Storage.Blob
Architecture
Each item is stored as:
- blob name:
{Prefix}{KeySettings<TKey>.AsString(key)} - blob content: JSON representation of
Entity<T, TKey>
That means the key appears twice:
- in the blob name
- in the serialized payload
Registration APIs
Direct builder registration
Available on all three patterns:
WithBlobStorageAsync(...)WithBlobStorage(...)
Supported for:
IRepositoryBuilder<T, TKey>ICommandBuilder<T, TKey>IQueryBuilder<T, TKey>
The sync overloads are wrappers over the async versions.
Connection service registration
Available overloads:
WithBlobStorage<T, TKey, TConnectionService>(...)
Supported for repository, command, and query registrations.
This path is useful when the container or credential is selected per tenant or request.
Direct builder example
This follows the test and sample usage style.
builder.Services.AddRepository<Car, Guid>(repositoryBuilder =>
{
repositoryBuilder.WithBlobStorage(blobStorageBuilder =>
{
blobStorageBuilder.Settings.ConnectionString = builder.Configuration["ConnectionStrings:Storage"];
blobStorageBuilder.Settings.ContainerName = "cars";
blobStorageBuilder.Settings.Prefix = "MyFolder/";
});
});
Connection service example
This mirrors the integration tests.
builder.Services.AddRepository<AppUser, AppUserKey>(repositoryBuilder =>
{
repositoryBuilder.WithBlobStorage<AppUser, AppUserKey, BlobStorageConnectionService>(
name: "blobstorage2");
});
Example connection service:
internal sealed class BlobStorageConnectionService
: IConnectionService<AppUser, AppUserKey, BlobContainerClientWrapper>
{
public BlobContainerClientWrapper GetConnection(string entityName, string? factoryName = null)
=> new()
{
Client = new BlobContainerClient("<connection-string>", entityName.ToLower())
};
}
Configuration and defaults
BlobStorageConnectionSettings exposes:
| Property | Notes |
|---|---|
ConnectionString |
Used when present. If both this and EndpointUri are set, connection string wins. |
EndpointUri |
Used for managed identity mode. This points to a container endpoint. |
ManagedIdentityClientId |
Null means system-assigned identity. |
ContainerName |
Used only in connection-string mode. Defaults to typeof(T).Name.ToLower(). |
Prefix |
Prepended to every blob name and used as the listing prefix for queries. |
ClientOptions |
Passed to the Azure Blob SDK. |
Default lifetimes:
- direct builder registration:
Singleton - connection service registration:
Scoped
Managed identity note
In managed identity mode, the builder constructs the client with:
new BlobContainerClient(Settings.EndpointUri, credential, Settings.ClientOptions)
So EndpointUri must already identify the container. ContainerName is not applied in that path.
Lifecycle and provisioning
Direct builder path
When you use WithBlobStorageAsync(...) or WithBlobStorage(...), the package calls CreateIfNotExistsAsync() during registration.
That behavior is visible in RepositoryFramework.UnitTest/Tests/Singularity/BlobStorageSingularityTest.cs: registration succeeds before any explicit warm-up.
Connection service path
When you use WithBlobStorage<T, TKey, TConnectionService>(...), container creation is your connection service's responsibility.
Bootstrap behavior
BlobStorageRepository<T, TKey>.BootstrapAsync() currently returns true and does nothing.
So like the Table Storage provider, the real provisioning behavior is tied to direct registration, not to WarmUpAsync().
CRUD behavior
GetAsync(key)checks blob existence and then downloads/deserializes the payloadExistAsync(key)checks blob existence onlyInsertAsync(key, value)uploads without overwriteUpdateAsync(key, value)uploads with overwrite enabledDeleteAsync(key)deletes the blob directly
Practical consequence:
- insert is create-only
- update behaves like upsert
Query behavior
QueryAsync(...) is a client-side scan.
The repository does this:
- list blobs by
Prefix - download each blob
- deserialize each payload
- pre-apply only the first
Whereexpression as an in-memory predicate - apply the full Repository Framework filter pipeline in memory
So there is:
- no blob tag query support
- no metadata filtering
- no server-side ordering or paging
- no projection pushdown
Query limitations to know about
- the first
Whereexpression is compiled toFunc<T, bool>and run locally OrderBy,ThenBy,Skip,Top, and paging all happen after values are materialized- aggregate operations such as
Count,Sum,Min,Max, andAveragerun in memory BatchAsync(...)is sequential and non-transactional
There is also an implementation detail worth knowing: query buffering uses Dictionary<T, Entity<T, TKey>>. If two blobs deserialize to values that compare equal under EqualityComparer<T>.Default, query enumeration can fail or collapse duplicates.
Named registrations and factory behavior
The optional name parameter is a Repository Framework factory name.
In connection-service mode the repository calls:
connectionService.GetConnection(typeof(T).Name, name)
So the connection service receives the CLR model name, not the configured ContainerName.
CQRS examples
await builder.Services.AddCommandAsync<Document, Guid>(async commandBuilder =>
{
await commandBuilder.WithBlobStorageAsync(blobStorageBuilder =>
{
blobStorageBuilder.Settings.ConnectionString = builder.Configuration["ConnectionStrings:Storage"];
});
});
await builder.Services.AddQueryAsync<Document, Guid>(async queryBuilder =>
{
await queryBuilder.WithBlobStorageAsync(blobStorageBuilder =>
{
blobStorageBuilder.Settings.ConnectionString = builder.Configuration["ConnectionStrings:Storage"];
blobStorageBuilder.Settings.Prefix = "documents/";
});
});
When to use this package
Use it when you want:
- simple key-addressed storage in Azure Blob Storage
- easy handling of complex keys through
KeySettings<TKey> - a repository backend that is straightforward to inspect and reason about
Avoid it when you need efficient server-side querying across large datasets, because the current implementation scans and deserializes blobs on the client side.
| 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
- Azure.Identity (>= 1.19.0)
- Azure.Storage.Blobs (>= 12.27.0)
- Rystem.RepositoryFramework.Abstractions (>= 10.0.7)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Rystem.RepositoryFramework.Infrastructure.Azure.Storage.Blob:
| Package | Downloads |
|---|---|
|
Rystem.RepositoryFramework.Cache.Azure.Storage.Blob
Rystem.RepositoryFramework allows you to use correctly concepts like repository pattern, CQRS and DDD. You have interfaces for your domains, auto-generated api, auto-generated HttpClient to simplify connection "api to front-end", a functionality for auto-population in memory of your models, a functionality to simulate exceptions and waiting time from external sources to improve your implementation/business test and load test. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 10.0.7 | 74 | 3/26/2026 |
| 10.0.6 | 154,863 | 3/3/2026 |
| 10.0.5 | 162 | 2/22/2026 |
| 10.0.4 | 189 | 2/9/2026 |
| 10.0.3 | 147,954 | 1/28/2026 |
| 10.0.1 | 209,370 | 11/12/2025 |
| 9.1.3 | 372 | 9/2/2025 |
| 9.1.2 | 764,839 | 5/29/2025 |
| 9.1.1 | 97,941 | 5/2/2025 |
| 9.0.32 | 186,722 | 4/15/2025 |
| 9.0.31 | 5,867 | 4/2/2025 |
| 9.0.30 | 88,876 | 3/26/2025 |
| 9.0.29 | 9,033 | 3/18/2025 |
| 9.0.28 | 269 | 3/17/2025 |
| 9.0.27 | 282 | 3/16/2025 |
| 9.0.26 | 280 | 3/13/2025 |
| 9.0.25 | 52,162 | 3/9/2025 |
| 9.0.21 | 772 | 3/6/2025 |
| 9.0.20 | 19,621 | 3/6/2025 |
| 9.0.19 | 357 | 3/6/2025 |