The official .NET driver for evitaDB — a specialized, fast e-commerce database.
It connects to a remote evitaDB server over its gRPC API and exposes the same session-based programming
model as the Java client, adapted to C# conventions: strongly
typed query DSL, sealed entity model, builder-based mutations and first-class async/await support
across the entire network surface.
| Driver | evitaDB server | .NET |
|---|---|---|
| current | 2026.2.x (the wire protocol also tolerates older servers via built-in fallbacks) | .NET 10 |
dotnet add package EvitaDB.Clientusing EvitaDB.Client;
using EvitaDB.Client.Config;
EvitaClientConfiguration configuration = new EvitaClientConfiguration.Builder()
.SetHost("demo.evitadb.io")
.SetPort(5555)
.SetUseGeneratedCertificate(false)
.SetUsingTrustedRootCaCertificate(true)
.Build();
using EvitaClient evita = await EvitaClient.Create(configuration);The builder also exposes mTLS (SetMtlsEnabled, client certificate paths), trust for the server's
self-generated certificate (SetUseGeneratedCertificate), plain-text mode (SetTlsEnabled(false)),
OpenTelemetry tracing (SetTraceEndpointUrl) and connection keep-alive tuning
(SetPingIntervalMilliseconds, SetIdleTimeoutMilliseconds).
Bring the query DSL into scope with a static import — queries then read almost identically to evitaQL and the Java DSL:
using System.Globalization;
using EvitaDB.Client.Models.Data;
using static EvitaDB.Client.Queries.IQueryConstraints;
IList<ISealedEntity> products = evita.QueryCatalog(
"evita",
session => session.QueryListOfSealedEntities(
Query(
Collection("Product"),
FilterBy(
AttributeEquals("status", "ACTIVE"),
EntityLocaleEquals(new CultureInfo("en"))
),
Require(
Page(1, 20),
EntityFetch(
AttributeContentAll(),
PriceContentRespectingFilter(),
ReferenceContentAllWithAttributes()
)
)
)
));Every query has three shapes: QueryOne* (single record), QueryList* (records only) and Query*
(full response with paging and extra results such as facet summary, hierarchy statistics or histograms):
EvitaResponse<ISealedEntity> response = session.QuerySealedEntity(query);
FacetSummary? facets = response.GetExtraResult<FacetSummary>();evita.UpdateCatalog("evita", session =>
{
EntityReference reference = session.UpsertEntity(
session.CreateNewEntity("Product")
.SetAttribute("name", new CultureInfo("en"), "Cool Product")
.SetAttribute("code", "cool-product-1"));
session.DeleteEntity("Product", 42);
});Schemas are defined the same way — catalog and entity schema builders produce mutations that are applied through the session:
evita.DefineCatalog("evita");
evita.UpdateCatalog("evita", session =>
{
session.GetCatalogSchema().OpenForWrite()
.WithAttribute<string>("code", thatIs => thatIs.UniqueGlobally())
.UpdateVia(session);
if (session.CatalogState == CatalogState.WarmingUp)
{
session.GoLiveAndClose();
}
});Every network call has an async counterpart accepting a CancellationToken — the sync methods are thin
facades over the same async core:
ISealedEntity? entity = await evita.QueryCatalogAsync(
"evita",
session => session.GetEntityAsync("Product", 1, EntityFetchAll().Requirements!),
cancellationToken);
await evita.UpdateCatalogAsync(
"evita",
session => session.UpsertEntityAsync(entityMutation));A read-write session on a live catalog is transactional. Besides the plain Close(), the driver exposes
the server's three commit phases as awaitable tasks:
EvitaClientSession session = evita.CreateReadWriteSession("evita");
await session.UpsertEntityAsync(mutation);
CommitProgress progress = session.CloseNowWithProgress();
await progress.OnConflictResolved; // conflicts checked
await progress.OnWalAppended; // durably written to the write-ahead log
await progress.OnChangesVisible; // visible to other sessionsCatalog and system change streams are exposed as IAsyncEnumerable, kept alive by server heartbeats:
await foreach (ChangeCatalogCapture capture in session.RegisterChangeCatalogCaptureAsync(request, ct))
{
Console.WriteLine(capture.Operation);
}The write-ahead-log history is available through GetMutationsHistory / GetMutationsHistoryAsync.
evita.Management() provides server status, configuration, catalog statistics, long-running task
tracking and file access. Catalog backup/restore and archival entity scopes (ArchiveEntity /
RestoreEntity) are available on the session and client.
dotnet restore EvitaDB.slnx
dotnet build EvitaDB.slnx
dotnet test EvitaDB.Test/EvitaDB.Test.csprojThe test suite starts disposable evitaDB containers via Testcontainers — a running Docker daemon is required.
| Environment variable | Purpose | Default |
|---|---|---|
EVITA_IMAGE_TAG |
Docker tag of evitadb/evitadb the integration tests run against |
2026.2.4 |
EVITA_DEMO_HOST / EVITA_DEMO_PORT |
Server with the demo dataset for the read-only demo query suite | demo.evitadb.io / 5555 |
| Path | Content |
|---|---|
EvitaDB.Client |
The driver itself (published as the EvitaDB.Client NuGet package) |
EvitaDB.Client/Protos |
gRPC protocol definitions, pinned to the targeted evitaDB release |
EvitaDB.Test |
xUnit integration test suite (Testcontainers + demo dataset) |
EvitaDB.QueryValidator |
Standalone tool that validates and evaluates evitaQL snippets (used by the evitaDB documentation pipeline) |
documentation/ |
Developer documentation — architecture, conventions, upgrade guides |
Developer documentation for contributors — including the architecture overview and the process for
adapting the driver to newer evitaDB versions — lives in documentation/.
Releases are produced by the release.yml workflow: every push to
master builds and tests the solution, derives the next semantic version from commit messages
(feat: → minor, (breaking) → major), publishes a GitHub release with the query validator binaries
and pushes the EvitaDB.Client package to NuGet.org via
Trusted Publishing (OIDC —
no long-lived API keys).
Apache 2.0 — © FG Forrest, a.s.