Database Providers
The same repository code runs against several database providers. Each provider ships as its own package and exposes a client factory plus a convenience repository factory. See Getting Started for the general initialization flow and dependency-injection setup.
Azure Cosmos DB
Package: Wemogy.Infrastructure.Database.Cosmos
var repository = CosmosDatabaseRepositoryFactory.CreateInstance<IUserRepository>(
"CONNECTION_STRING_HERE",
"DATABASE_NAME",
true); // enable insecure development mode for the local emulator
Or via dependency injection:
var databaseClientFactory = new CosmosDatabaseClientFactory("CONNECTION_STRING_HERE", "DATABASE_NAME");
services
.AddDatabase(databaseClientFactory)
.AddRepository<IUserRepository>();
Provider specifics:
- Property names are serialized as camelCase, and
nullvalues are omitted. - The
[ETag]attribute enables optimistic concurrency. - Transactional batches are mapped onto the native
TransactionalBatchof the Cosmos SDK. - Partial updates are mapped onto
PatchItem, and a patch condition onto a filter predicate, which accepts comparisons but no arithmetic on document fields. - The change feed is mapped onto the change feed processor of the Cosmos SDK.
It needs a lease container, configured with the
leaseContainerNameargument of the factory and defaulting toleases, which has to exist with the partition key path/id. - Multi-tenancy is supported.
- The third constructor argument enables insecure development mode (gateway connection mode and relaxed certificate validation) for use with the local Cosmos DB emulator.
In-Memory
Package: Wemogy.Infrastructure.Database.InMemory
The in-memory provider keeps data in process and requires no connection string. It is meant for unit tests, so the exact same repository code can be exercised without a real database.
var repository = InMemoryDatabaseRepositoryFactory.CreateInstance<IUserRepository>();
Provider specifics:
- No external dependency or connection string.
- The store is shared per entity type for the whole process, so every repository over the same
entity sees the same data regardless of which factory created it. Reset it between tests with
DeleteAsync(x => true). - Multi-tenancy is supported.
- Optimistic concurrency via the
[ETag]attribute is supported, with the same semantics as Cosmos DB: every write assigns a new eTag, aReplaceAsyncwith a stale eTag fails the precondition, and anUpsertAsynccarries no precondition. - Sort keys are compared ordinally, matching Cosmos DB, so the order does not depend on the culture of the machine running the tests.
- Transactional batches are supported with the same semantics as Cosmos DB: every operation is validated before any of them is applied, so a failing batch leaves the store untouched.
- Partial updates are supported, applied under the store's lock. A patch condition is compiled and evaluated in process, which accepts more than the Cosmos DB filter predicate does - a condition doing arithmetic on document fields passes here and is refused there.
- The change feed replays the writes of the store in order, with the same ordering, checkpointing and redelivery semantics. One logical partition stands in for one physical partition key range, and lease contention between two processors sharing a name is not modelled.
Reference the in-memory package in your test project and Cosmos DB in your
application. Because both implement the same IDatabaseClient, your repository
logic and tests stay provider-independent.
Feature support matrix
| Feature | Cosmos DB | In-Memory |
|---|---|---|
| CRUD, querying, sorting & pagination | ✅ | ✅ |
| Soft delete | ✅ | ✅ |
| Read & property filters | ✅ | ✅ |
| Multi-tenancy | ✅ | ✅ |
| Optimistic concurrency (ETag) | ✅ | ✅ |
| Transactional batch | ✅ | ✅ |
| Partial update (Patch) | ✅ | ✅ |
| Change feed (latest version) | ✅ | ✅ |
| Change feed (all versions and deletes) | ✅ ¹ | ✅ |
¹ Needs a container configured with a full fidelity retention window, and is not served by the Linux vNext emulator.