![]() |
VOOZH | about |
dotnet add package Rystem.RepositoryFramework.Abstractions --version 10.0.8
NuGet\Install-Package Rystem.RepositoryFramework.Abstractions -Version 10.0.8
<PackageReference Include="Rystem.RepositoryFramework.Abstractions" Version="10.0.8" />
<PackageVersion Include="Rystem.RepositoryFramework.Abstractions" Version="10.0.8" />Directory.Packages.props
<PackageReference Include="Rystem.RepositoryFramework.Abstractions" />Project file
paket add Rystem.RepositoryFramework.Abstractions --version 10.0.8
#r "nuget: Rystem.RepositoryFramework.Abstractions, 10.0.8"
#:package Rystem.RepositoryFramework.Abstractions@10.0.8
#addin nuget:?package=Rystem.RepositoryFramework.Abstractions&version=10.0.8Install as a Cake Addin
#tool nuget:?package=Rystem.RepositoryFramework.Abstractions&version=10.0.8Install as a Cake Tool
Core contracts, query primitives, registration builders, and runtime metadata for the Rystem repository ecosystem.
This is the foundation for the whole Repository Framework area documented in src/Repository/README.md.
It defines:
dotnet add package Rystem.RepositoryFramework.Abstractions
The current package metadata in src/Repository/RepositoryFramework.Abstractions/RepositoryFramework.Abstractions.csproj is:
Rystem.RepositoryFramework.Abstractions10.0.6net10.0This package builds on top of Rystem.DependencyInjection.
At a high level, this package is organized around these areas.
| Area | Purpose |
|---|---|
| Pattern interfaces | Low-level storage contracts such as IRepositoryPattern<T, TKey> |
| Consumer interfaces | DI-facing contracts such as IRepository<T, TKey> |
| Service registration builders | AddRepository, AddCommand, AddQuery, and their async variants |
| Query model | QueryBuilder<T, TKey>, IFilterExpression, paging, aggregate operations |
| Keys and state models | IKey, IDefaultKey, Key<T1,...>, Entity<T, TKey>, State<T, TKey> |
| Business and translation hooks | interceptors, examples, exposure rules, filter translation |
| Runtime metadata | RepositoryFrameworkRegistry and RepositoryFrameworkService |
IRepositoryPattern<T, TKey>, ICommandPattern<T, TKey>, IQueryPattern<T, TKey>IRepository<T, TKey>, ICommand<T, TKey>, IQuery<T, TKey>AddRepository, AddCommand, AddQuery, plus async variantsSetStorage, SetStorageWithOptions, SetStorageAndBuildOptions, SetStorageAndBuildOptionsAsync, SetStorageAndServiceConnectionIKey, IDefaultKey, Key<T1> through Key<T1, T2, T3, T4, T5>, and KeySettings<TKey>QueryBuilder<T, TKey>, FilterExpression, SerializableFilter, metadata, paging, and aggregate operationsThis package does not ship a database provider by itself. Instead, it gives you a stable abstraction layer for three concerns:
Most other packages in src/Repository are adapters built on top of these abstractions.
Implement one of these in your storage class.
// Full repository (read + write)
public interface IRepositoryPattern<T, TKey> : ICommandPattern<T, TKey>, IQueryPattern<T, TKey>
where TKey : notnull { }
// Write only
public interface ICommandPattern<T, TKey>
where TKey : notnull
{
Task<State<T, TKey>> InsertAsync(TKey key, T value, CancellationToken cancellationToken = default);
Task<State<T, TKey>> UpdateAsync(TKey key, T value, CancellationToken cancellationToken = default);
Task<State<T, TKey>> DeleteAsync(TKey key, CancellationToken cancellationToken = default);
IAsyncEnumerable<BatchResult<T, TKey>> BatchAsync(BatchOperations<T, TKey> operations, CancellationToken cancellationToken = default);
}
// Read only
public interface IQueryPattern<T, TKey>
where TKey : notnull
{
Task<State<T, TKey>> ExistAsync(TKey key, CancellationToken cancellationToken = default);
Task<T?> GetAsync(TKey key, CancellationToken cancellationToken = default);
IAsyncEnumerable<Entity<T, TKey>> QueryAsync(IFilterExpression filter, CancellationToken cancellationToken = default);
ValueTask<TProperty> OperationAsync<TProperty>(OperationType<TProperty> operation, IFilterExpression filter, CancellationToken cancellationToken = default);
}
Both query and command abstractions also inherit the non-generic bootstrap contract through their base interfaces, so storage implementations can participate in warm-up/startup bootstrap logic.
Inject these into application services instead of the pattern interfaces directly.
IRepository<T, TKey> // read + write + query extensions
ICommand<T, TKey> // write only
IQuery<T, TKey> // read only
The consumer interfaces are what the registration builders expose through DI and named factories.
builder.Services.AddRepository<AppUser, Guid>(repositoryBuilder =>
{
repositoryBuilder.SetStorage<AppUserStorage>();
});
builder.Services.AddCommand<AppUser, Guid>(commandBuilder =>
{
commandBuilder.SetStorage<AppUserCommandStorage>();
});
builder.Services.AddQuery<AppUser, Guid>(queryBuilder =>
{
queryBuilder.SetStorage<AppUserQueryStorage>();
});
Use async variants when the builder itself needs asynchronous setup.
await builder.Services.AddRepositoryAsync<AppUser, Guid>(async repositoryBuilder =>
{
repositoryBuilder.SetStorage<AppUserStorage>();
await Task.CompletedTask;
});
await builder.Services.AddCommandAsync<AppUser, Guid>(async commandBuilder =>
{
commandBuilder.SetStorage<AppUserCommandStorage>();
await Task.CompletedTask;
});
await builder.Services.AddQueryAsync<AppUser, Guid>(async queryBuilder =>
{
queryBuilder.SetStorage<AppUserQueryStorage>();
await Task.CompletedTask;
});
All repository builders eventually flow through the storage registration methods in RepositoryBaseBuilder.
SetStorage<TStorage>()Use this when the storage can be resolved directly from DI.
builder.Services.AddRepository<AppUser, Guid>(repositoryBuilder =>
{
repositoryBuilder.SetStorage<AppUserStorage>();
});
SetStorageWithOptions<TStorage, TStorageOptions>()Use this when the storage consumes a simple options object implementing IFactoryOptions.
builder.Services.AddRepository<AppUser, Guid>(repositoryBuilder =>
{
repositoryBuilder.SetStorageWithOptions<AppUserStorage, AppUserStorageOptions>(options =>
{
options.ConnectionString = builder.Configuration["ConnectionStrings:Default"]!;
});
});
SetStorageAndBuildOptions<TStorage, TStorageOptions, TConnection>()Use this when the builder must transform fluent configuration into a factory-backed connection/options object.
builder.Services.AddRepository<AppUser, Guid>(repositoryBuilder =>
{
repositoryBuilder.SetStorageAndBuildOptions<AppUserStorage, AppUserBuilder, AppUserConnection>(options =>
{
options.Name = "users";
});
});
SetStorageAndBuildOptionsAsync<TStorage, TStorageOptions, TConnection>()Same as the previous one, but the options builder can perform asynchronous work.
await builder.Services.AddRepositoryAsync<AppUser, Guid>(async repositoryBuilder =>
{
await repositoryBuilder.SetStorageAndBuildOptionsAsync<AppUserStorage, AppUserBuilder, AppUserConnection>(options =>
{
options.Name = "users";
});
});
SetStorageAndServiceConnection<TStorage, TConnectionService, TConnectionClient>()Use this when the actual connection or client is request-aware or tenant-aware.
public sealed class TenantAwareConnectionService : IConnectionService<Order, Guid, DbConnection>
{
private readonly ITenantResolver _tenantResolver;
public TenantAwareConnectionService(ITenantResolver tenantResolver)
=> _tenantResolver = tenantResolver;
public DbConnection GetConnection(string entityName, string? factoryName = null)
{
var connectionString = _tenantResolver.GetConnectionString(entityName, factoryName);
return new SqlConnection(connectionString);
}
}
builder.Services.AddRepository<Order, Guid>(repositoryBuilder =>
{
repositoryBuilder.SetStorageAndServiceConnection<OrderStorage, TenantAwareConnectionService, DbConnection>();
});
SetStorage* methods default to ServiceLifetime.Scoped.SetStorage* overload accepts an optional name and serviceLifetime.name is stored as the repository FactoryName in the runtime registry and is how named factories resolve a specific storage.One model can be backed by multiple repositories or providers at the same time. The common pattern is to register each one with a name, then resolve it through IFactory<TService>.
This is heavily used in the integration tests and sample web API.
builder.Services.AddRepository<AppUser, AppUserKey>(repositoryBuilder =>
{
repositoryBuilder.SetStorage<PrimaryAppUserStorage>(name: "primary");
repositoryBuilder.SetStorage<ArchiveAppUserStorage>(name: "archive");
});
public sealed class AppUserImportService
{
private readonly IFactory<IRepository<AppUser, AppUserKey>> _repositoryFactory;
public AppUserImportService(IFactory<IRepository<AppUser, AppUserKey>> repositoryFactory)
=> _repositoryFactory = repositoryFactory;
public Task<AppUser?> GetFromArchiveAsync(AppUserKey key, CancellationToken cancellationToken = default)
{
var repository = _repositoryFactory.Create("archive")!;
return repository.GetAsync(key, cancellationToken);
}
}
The same pattern works for:
IFactory<IRepository<T, TKey>>IFactory<IQuery<T, TKey>>IFactory<ICommand<T, TKey>>This makes it easy to switch between environments, fallback providers, multi-tenant routing, cache layers, or migration tooling without changing the domain-facing contract.
Key handling is more flexible than the old docs suggest. KeySettings<TKey> supports several strategies.
These work out of the box:
stringGuidDateTimeDateTimeOffsetTimeSpannintnuintbuilder.Services.AddRepository<AppUser, Guid>(...);
builder.Services.AddRepository<Product, int>(...);
builder.Services.AddRepository<Session, string>(...);
Key<T1, T2, ...>You can use the built-in Key<> helpers for common composite-key scenarios.
builder.Services.AddRepository<Order, Key<int, string>>(repositoryBuilder =>
{
repositoryBuilder.SetStorage<OrderStorage>();
});
var key = new Key<int, string>(42, "region-eu");
var order = await repository.GetAsync(key);
IKeyImplement IKey when you want full control over string serialization.
public sealed class AppUserKey : IKey
{
public string TenantId { get; set; } = string.Empty;
public Guid UserId { get; set; }
public static IKey Parse(string keyAsString)
{
var parts = keyAsString.Split('-', 2);
return new AppUserKey { TenantId = parts[0], UserId = Guid.Parse(parts[1]) };
}
public string AsString() => $"{TenantId}-{UserId}";
}
IDefaultKeyImplement IDefaultKey when you want the framework to serialize all key properties using the default separator.
public sealed class OrderKey : IDefaultKey
{
public int OrderId { get; set; }
public string Region { get; set; } = string.Empty;
}
builder.Services.AddDefaultSeparatorForDefaultKeyInterface("$$$");
If TKey is not primitive, not IKey, and not IDefaultKey, KeySettings<TKey> still supports it as long as the type exposes properties. In that case it falls back to JSON serialization.
This behavior is covered by the key tests and the class-key repository tests.
public sealed class ClassAnimalKey
{
public string Area { get; set; } = string.Empty;
public int Id { get; set; }
public Guid CorrelationId { get; set; }
public ClassAnimalKey() { }
public ClassAnimalKey(string area, int id, Guid correlationId)
=> (Area, Id, CorrelationId) = (area, id, correlationId);
}
builder.Services.AddRepository<ClassAnimal, ClassAnimalKey>(repositoryBuilder =>
{
repositoryBuilder.SetStorage<ClassAnimalRepository>();
});
The practical rule is simple: if the key can be converted to and from a stable string representation, the abstraction layer can carry it through providers and APIs.
State<T, TKey>All command methods return State<T, TKey>.
public class State<T, TKey>
{
public bool IsOk { get; set; }
public Entity<T, TKey>? Entity { get; set; }
public int? Code { get; set; }
public string? Message { get; set; }
public bool HasEntity { get; }
}
Useful factory helpers include:
return State.Ok(value, key);
return State.NotOk(value, key);
return State.Default(isOk, value, key);
return await State.OkAsTask(value, key);
return await State.NotOkAsTask(value, key);
Entity<T, TKey>Query operations return Entity<T, TKey> so callers can keep both the key and the value.
public class Entity<T, TKey>
{
public TKey? Key { get; set; }
public T? Value { get; set; }
public bool HasValue { get; }
public bool HasKey { get; }
public State<T, TKey> ToOkState();
public State<T, TKey> ToNotOkState();
}
Use BatchOperations<T, TKey> and BatchResult<T, TKey> when the provider supports grouped write operations.
var batch = new BatchOperations<AppUser, Guid>()
.AddInsert(Guid.NewGuid(), new AppUser { Name = "Alice" })
.AddUpdate(existingId, updatedUser)
.AddDelete(oldId);
await foreach (var result in command.BatchAsync(batch))
{
// result.Command
// result.Key
// result.State
}
The command and repository consumers also expose the fluent helper:
await repository.CreateBatchOperation()
.AddInsert(key1, value1)
.AddDelete(key2)
.ExecuteAsync()
.ToListAsync();
IQuery<T, TKey> and IRepository<T, TKey> expose extension methods that create a QueryBuilder<T, TKey>.
var items = await repository
.Where(x => x.IsActive)
.OrderByDescending(x => x.Price)
.Skip(20)
.Take(10)
.ToListAsync();
foreach (var entity in items)
Console.WriteLine(entity.Value!.Name);
List<Product> values = await repository
.Where(x => x.IsActive)
.ToListAsEntityAsync();
| Method | Description |
|---|---|
Where(expr) |
Filter by entity predicate |
WhereKey(expr) |
Filter by key predicate |
Take(n) |
Limit results |
Skip(n) |
Offset results |
OrderBy(expr) |
Ascending sort |
OrderByDescending(expr) |
Descending sort |
ThenBy(expr) |
Secondary ascending sort |
ThenByDescending(expr) |
Secondary descending sort |
AnyAsync(expr?) |
Returns bool |
FirstOrDefaultAsync(expr?) |
Returns Entity<T, TKey>? |
FirstAsync(expr?) |
Returns Entity<T, TKey> |
FirstOrDefaultByKeyAsync(expr?) |
Returns first entity filtered on key |
FirstByKeyAsync(expr?) |
Returns first entity filtered on key |
PageAsync(page, pageSize) |
Returns Page<T, TKey> |
ToListAsync() |
Returns List<Entity<T, TKey>> |
ToListAsEntityAsync() |
Returns List<T> |
QueryAsync() |
Returns IAsyncEnumerable<Entity<T, TKey>> |
QueryAsEntityAsync() |
Returns IAsyncEnumerable<T> |
CountAsync() |
Aggregate count |
SumAsync(expr) |
Aggregate sum |
AverageAsync(expr) |
Aggregate average |
MaxAsync(expr) |
Aggregate max |
MinAsync(expr) |
Aggregate min |
OperationAsync(operation) |
Custom aggregate operation |
AddMetadata(key, value) |
Attach metadata to the filter |
PageAsync validates that page >= 1 and pageSize >= 1.PageAsync calculates total pages using a separate Count operation.GroupByAsync is not translated into provider-native grouping. It first enumerates QueryAsync() and then groups client-side.Page<AppUser, AppUserKey> firstPage = await repository
.Where(x => x.Id > 0)
.OrderByDescending(x => x.Id)
.PageAsync(page: 1, pageSize: 20);
IFilterExpression is the portable query description that storage providers receive in QueryAsync and OperationAsync.
This is the bridge between LINQ-like consumer code and your provider implementation.
Where, OrderBy, Skip, and TakeSerialize() into a SerializableFilterToKey()GetFilters(...)Translate(...)For in-memory or adapter-style repositories, the simplest pattern is to let the filter apply itself.
public async IAsyncEnumerable<Entity<AppUser, AppUserKey>> QueryAsync(
IFilterExpression filter,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
await Task.Yield();
foreach (var item in filter.Apply(_items))
{
cancellationToken.ThrowIfCancellationRequested();
yield return Entity.Default(item, new AppUserKey(item.Id));
}
}
AddMetadata(key, value) is useful when your provider needs extra information that is not part of the entity predicate itself, such as tenant, partition, read consistency, or a custom projection mode.
var query = repository
.Where(x => x.IsActive)
.AddMetadata("tenant", "eu-west")
.AddMetadata("mode", "snapshot");
The metadata becomes part of the filter representation available to the storage layer through IFilterExpression.
Business interceptors let you wrap every repository operation with validation, auditing, policy checks, or side effects.
builder.Services.AddRepository<AppUser, Guid>(repositoryBuilder =>
{
repositoryBuilder.SetStorage<AppUserStorage>();
repositoryBuilder
.AddBusiness()
.AddBusinessBeforeInsert<AppUserValidation>()
.AddBusinessAfterInsert<AppUserAudit>()
.AddBusinessBeforeDelete<AppUserDeletionGuard>();
});
builder.Services
.AddBusinessForRepository<AppUser, Guid>()
.AddBusinessBeforeUpdate<AppUserUpdateValidation>()
.AddBusinessAfterUpdate<AppUserUpdateAudit>();
builder.Services.ScanBusinessForRepositoryFramework();
builder.Services.ScanBusinessForRepositoryFramework(typeof(MyAssemblyMarker).Assembly);
ScanBusinessForRepositoryFramework() inspects all before/after business interfaces for the repositories already registered in the framework registry.
| Interface | Triggered |
|---|---|
IRepositoryBusinessBeforeInsert<T, TKey> |
Before InsertAsync |
IRepositoryBusinessAfterInsert<T, TKey> |
After InsertAsync |
IRepositoryBusinessBeforeUpdate<T, TKey> |
Before UpdateAsync |
IRepositoryBusinessAfterUpdate<T, TKey> |
After UpdateAsync |
IRepositoryBusinessBeforeDelete<T, TKey> |
Before DeleteAsync |
IRepositoryBusinessAfterDelete<T, TKey> |
After DeleteAsync |
IRepositoryBusinessBeforeBatch<T, TKey> |
Before BatchAsync |
IRepositoryBusinessAfterBatch<T, TKey> |
After BatchAsync |
IRepositoryBusinessBeforeGet<T, TKey> |
Before GetAsync |
IRepositoryBusinessAfterGet<T, TKey> |
After GetAsync |
IRepositoryBusinessBeforeExist<T, TKey> |
Before ExistAsync |
IRepositoryBusinessAfterExist<T, TKey> |
After ExistAsync |
IRepositoryBusinessBeforeQuery<T, TKey> |
Before QueryAsync |
IRepositoryBusinessAfterQuery<T, TKey> |
After QueryAsync |
IRepositoryBusinessBeforeOperation<T, TKey> |
Before OperationAsync |
IRepositoryBusinessAfterOperation<T, TKey> |
After OperationAsync |
Priority controls ordering. Lower values run first.
The translation builder is what lets consumer code keep writing filters against the domain model while the provider translates them to a different storage model.
This is covered by the translation tests.
builder.Services.AddRepository<Translatable, string>(repositoryBuilder =>
{
repositoryBuilder
.SetStorage<TranslatableRepository>()
.Translate<ToTranslateSomething>()
.With(x => x.Foolish, x => x.Folle)
.With(x => x.Id, x => x.IdccnlValidita)
.With(x => x.CcnlId, x => x.Idccnl)
.With(x => x.From, x => x.DataInizio)
.With(x => x.To, x => x.DataFine)
.AndTranslate<ToTranslateSomethingElse>()
.With(x => x.Foolish, x => x.Folle)
.With(x => x.Id, x => x.IdccnlValidita)
.With(x => x.CcnlId, x => x.Idccnl);
});
Common helpers include:
Translate<TTranslated>()With(domainProperty, translatedProperty)WithKey(...)WithSamePorpertiesName()AndTranslate<TTranslated>()This is especially useful for EF models, API DTOs, cache projections, or legacy schemas where names do not line up with the public domain model.
These settings matter when the repository is later surfaced through Rystem.RepositoryFramework.Api.Server.
builder.Services.AddRepository<AppUser, Guid>(repositoryBuilder =>
{
repositoryBuilder.SetStorage<AppUserStorage>();
repositoryBuilder.SetExposable(RepositoryMethods.All);
repositoryBuilder.SetOnlyQueryExposable();
repositoryBuilder.SetOnlyCommandExposable();
repositoryBuilder.SetExposable(RepositoryMethods.Get | RepositoryMethods.Query);
repositoryBuilder.SetNotExposable();
});
RepositoryMethods also includes Bootstrap, so the bootstrap endpoint can be included or hidden when you expose repositories as APIs.
builder.Services.AddRepository<AppUser, Guid>(repositoryBuilder =>
{
repositoryBuilder.SetStorage<AppUserStorage>();
repositoryBuilder.SetExamples(
new AppUser { Name = "Alice", Email = "alice@example.com" },
Guid.NewGuid());
});
If a storage implementation needs startup work such as schema creation, seeding, or client warm-up, implement the bootstrap contract.
public sealed class AppUserStorage : IRepositoryPattern<AppUser, Guid>, IBootstrapPattern
{
public async ValueTask<bool> BootstrapAsync(CancellationToken cancellationToken = default)
{
await EnsureTableExistsAsync(cancellationToken);
return true;
}
// other IRepositoryPattern members omitted
}
Important: bootstrap does not run just because AddRepository was called.
In the real tests and sample web API, bootstrap is executed by calling WarmUpAsync() on the built service provider:
var app = builder.Build();
await app.Services.WarmUpAsync();
That is the practical startup lifecycle to document and rely on.
You can run synchronous or asynchronous logic after the repository builder delegate finishes.
builder.Services.AddRepository<AppUser, Guid>(repositoryBuilder =>
{
repositoryBuilder.SetStorage<AppUserStorage>();
repositoryBuilder.AfterBuild = () =>
{
Console.WriteLine("AppUser repository registered.");
};
repositoryBuilder.AfterBuildAsync = async () =>
{
await ValidateSchemaAsync();
};
});
The important detail is timing: AfterBuild and AfterBuildAsync run after the whole AddRepository or AddCommand or AddQuery builder delegate returns, not after each individual SetStorage* call.
RepositoryFrameworkRegistry is registered automatically as a singleton. It tracks every repository, command, and query configured through the framework.
public sealed class RepositoryDiagnosticsService
{
private readonly RepositoryFrameworkRegistry _registry;
public RepositoryDiagnosticsService(RepositoryFrameworkRegistry registry)
=> _registry = registry;
public void PrintAll()
{
foreach (var (_, service) in _registry.Services)
{
Console.WriteLine(
$"{service.ModelType.Name} {service.Type} -> {service.ImplementationType.Name} [{service.FactoryName}]");
}
}
}
RepositoryFrameworkService metadata| Property | Description |
|---|---|
ModelType |
The domain model type |
KeyType |
The key type |
InterfaceType |
The DI-facing contract |
ImplementationType |
The storage implementation |
ExposedMethods |
API-visible methods |
ServiceLifetime |
DI lifetime used by registration |
Type |
Repository, Command, or Query |
FactoryName |
Named registration key, empty when default |
Policies |
Authorization policy names used by UI/API tooling |
This registry is what later packages use to expose repositories as APIs, create documentation, or inspect configured services.
| Package | Purpose |
|---|---|
Rystem.RepositoryFramework.Infrastructure.InMemory |
In-memory storage and test-friendly provider |
Rystem.RepositoryFramework.Infrastructure.EntityFramework |
EF Core adapter |
Rystem.RepositoryFramework.Api.Server |
Auto-generate REST APIs from repository registrations |
Rystem.RepositoryFramework.Api.Client |
.NET and TypeScript client adapters |
If you are continuing through the repository area, this README is the conceptual base to read before the infrastructure packages.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
Showing the top 5 NuGet packages that depend on Rystem.RepositoryFramework.Abstractions:
| Package | Downloads |
|---|---|
|
Rystem.RepositoryFramework.Api.Server
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. |
|
|
Rystem.RepositoryFramework.Api.Client
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. |
|
|
Rystem.RepositoryFramework.Infrastructure.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. |
|
|
Rystem.RepositoryFramework.Infrastructure.Azure.Storage.Table
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. |
|
|
Rystem.RepositoryFramework.Cache
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. |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 10.0.8 | 6,299 | 5/13/2026 |
| 10.0.7 | 413 | 3/26/2026 |
| 10.0.6 | 434,044 | 3/3/2026 |
| 10.0.5 | 341 | 2/22/2026 |
| 10.0.4 | 374 | 2/9/2026 |
| 10.0.3 | 148,110 | 1/28/2026 |
| 10.0.1 | 209,562 | 11/12/2025 |
| 9.1.3 | 706 | 9/2/2025 |
| 9.1.2 | 765,284 | 5/29/2025 |
| 9.1.1 | 98,226 | 5/2/2025 |
| 9.0.32 | 187,028 | 4/15/2025 |
| 9.0.31 | 6,147 | 4/2/2025 |
| 9.0.30 | 89,103 | 3/26/2025 |
| 9.0.29 | 9,343 | 3/18/2025 |
| 9.0.28 | 506 | 3/17/2025 |
| 9.0.27 | 483 | 3/16/2025 |
| 9.0.26 | 551 | 3/13/2025 |
| 9.0.25 | 52,418 | 3/9/2025 |
| 9.0.23 | 309 | 3/9/2025 |
| 9.0.21 | 1,052 | 3/6/2025 |