About this project

Overview This repository, sqlite-multi-tenant, is a multi-tenant SQLite database manager for .NET (described in the repository metadata as providing per-tenant isolation, migrations and backups). The README is a class-by-class reference: each section documents one service, helper or validator and illustrates it with C# usage examples. It is written as API documentation rather than a getting-started guide, so the material below reflects what the README actually demonstrates. Multi-tenancy strategies The README's end-to-end isolation tests describe two supported approaches: - Connection-per-tenant: each tenant is backed by its own physical SQLite file, giving file-level isolation. A tenant's connection string points at only that tenant's database. - Shared-schema: all tenants share a single SQLite file, and a TenantId discriminator column scopes every query so that each tenant only reads or writes its own rows. The isolation tests are presented as deliberately hostile checks that a tenant cannot read, update or delete another tenant's rows under either model. The sample test code creates per-tenant temp database files, inserts tenant-tagged documents, and asserts that querying with a TenantId filter returns only that tenant's titles. The same pattern is shown for a shared file containing rows for several tenants. Helper methods in the samples build connection strings, create a Documents table with Id, TenantId and Title columns, insert rows with parameterized commands, and read titles filtered by tenant. Integrity checking IntegrityCheckService performs SQLite PRAGMA integrity_check operations across tenant databases. Documented entry points: - Check a single tenant by id. - Check an explicit list of tenants, with a maxDegreeOfParallelism argument. - Check all tenants in the system, also with configurable parallelism. - Check only active tenants. Results are surfaced as TenantIntegrityCheckResult objects exposing at least TenantId and IsOk. Configurable parallelism is presented as a way to manage system load during validation. Tenant context helpers TenantContextHelperExtensions adds extension methods to TenantContextHelper for working inside multi-tenant scopes. The README shows: checking whether the current tenant matches a target id, creating a validated scope that can carry a tenant id and a user id and is used in a using block, retrieving the required tenant context, retrieving the required tenant id directly, and executing an action or a value-returning function inside a specified tenant context. These are aimed at reducing repetitive plumbing around tenant-aware code paths. Middleware validation Two validators are documented: - RateLimitingMiddlewareValidation validates a RateLimitingMiddleware instance, a RateLimitingConfig object (with fields such as MaxRequestsPerSecond, MaxBurst, WindowSize, Enabled and BanDuration), a RateLimitExceededResult (IsExceeded, RetryAfter, CurrentRequestCount, Limit, Window), and RateLimitStatistics (TotalRequests, AllowedRequests, DeniedRequests, PeakRequestsPerSecond, CurrentActiveLimits). For each overload the README shows Validate returning a list of problem strings, IsValid returning a boolean, and EnsureValid throwing when the input is invalid. A workflow example validates middleware configuration before use and catches the resulting argument exception. - ErrorHandlingMiddlewareValidation provides extension methods that validate an ErrorHandlingMiddleware instance and Result objects. It checks for null references, consistency between success flags and error messages, and that successful results carry a non-default value. The documented surface is Validate, IsValid and EnsureValid on the middleware, plus the same three methods on Result values, so invariants can be enforced early in the request pipeline. Settings access SettingsControllerExtensions adds strongly typed and batch operations to SettingsController. Documented methods include: reading a setting as a concrete type, optionally with a custom parse function (for example for DateTime); writing a strongly typed value; updating a dictionary of settings in one batch call; testing whether a setting exists; and retrieving settings filtered by a predicate, returning a list of setting values. Results are wrapped in an API response object with a Data payload, as shown by the OkObjectResult checks in the examples. Serialization utilities - ReportGeneratorJsonExtensions wraps System.Text.Json serialization for monitoring data: health summaries, operation statistics and performance metrics. It documents ToJson for writing, FromJsonToOperationStatistics for reading statistics, and TryFromJson for performance metrics with a boolean success result. - StringUtilitiesJsonExtensions serializes and deserializes strings, with variants that attach a SHA256 hash or convert to snake_case, plus a try-deserialize method that reports success without throwing. Testing utilities TenantNameValidatorTestsExtensions supplies assertion-style helpers for tenant name validation: verifying that a name maps to an expected normalized tenant id, that a name is considered a valid tenant id, that an invalid name yields a specific expected error message, and enumerating the built-in collections of invalid tenant ids with their errors and valid name-to-id mappings. These are meant to be reused from test suites. Notes for evaluation The README is documentation of individual APIs with usage snippets; it does not include installation instructions, package names, supported .NET versions, migration or backup walkthroughs, or license and contribution details, even though migrations and backups are mentioned in the repository description. The samples reference namespaces such as SqliteMultiTenant.Services, SqliteMultiTenant.Models, SqliteMultiTenant.Utilities, SqliteMultiTenant.Middleware, SqliteMultiTenant.Monitoring, SqliteMultiTenant.Validation and SqliteMultiTenant.Api.Controllers, and they depend on System.Data.SQLite and a test framework. Readers should treat the samples as illustrative and confirm current APIs, packaging and isolation guarantees against the source before adopting them. The repeated blocks at the end of the README suggest some duplication in the document itself.