DotNET client usage
The .NET client resolves a namespace for every event store operation. You can configure namespace resolution by passing an IEventStoreNamespaceResolver implementation to the ChronicleClient constructor.
IEventStoreNamespaceResolver
Section titled “IEventStoreNamespaceResolver”public interface IEventStoreNamespaceResolver{ EventStoreNamespaceName Resolve();}The resolver returns the namespace name to use for the current context.
Built-in resolvers
Section titled “Built-in resolvers”DefaultEventStoreNamespaceResolver
Section titled “DefaultEventStoreNamespaceResolver”Always returns the default namespace. Use this when you do not need tenant isolation. This is the default when no resolver is supplied.
ClaimsBasedNamespaceResolver
Section titled “ClaimsBasedNamespaceResolver”Resolves the namespace from the current principal’s claims. This is useful when you have an authenticated user and want to map the tenant from a claim.
// Uses the default claim type "tenant_id"var client = new ChronicleClient( options, namespaceResolver: new ClaimsBasedNamespaceResolver("tenant_id"));
// Uses a custom claim typevar client = new ChronicleClient( options, namespaceResolver: new ClaimsBasedNamespaceResolver("custom_tenant_claim"));If the claim is not found or the user is not authenticated, the default namespace is used.
Passing a resolver to ChronicleClient
Section titled “Passing a resolver to ChronicleClient”For console or direct-client scenarios, pass the resolver as a constructor parameter:
var resolver = new DefaultEventStoreNamespaceResolver();var client = new ChronicleClient(options, namespaceResolver: resolver);Configuring in a hosted application
Section titled “Configuring in a hosted application”When using IHostApplicationBuilder (worker service or web app), configure the resolver through ChronicleClientOptions or directly via IChronicleBuilder:
// Via options (type is resolved from DI)builder.AddCratisChronicle(options =>{ options.EventStore = "my-store"; options.EventStoreNamespaceResolverType = typeof(TenantNamespaceResolver);});
// Via builder (instance is used directly)builder.AddCratisChronicle( configureOptions: options => options.EventStore = "my-store", configure: b => b.WithNamespaceResolver(new TenantNamespaceResolver(config)));Custom resolvers
Section titled “Custom resolvers”Implement a resolver when your namespace comes from a custom context, such as a tenant provider or a request-scoped service.
If your application uses Arc Tenancy, you can resolve the namespace from its tenant context. See Arc Tenancy.
public class TenantNamespaceResolver : IEventStoreNamespaceResolver{ readonly ITenantContext _tenantContext;
public TenantNamespaceResolver(ITenantContext tenantContext) { _tenantContext = tenantContext; }
public EventStoreNamespaceName Resolve() => _tenantContext.CurrentTenantId;}var client = new ChronicleClient(options, namespaceResolver: new TenantNamespaceResolver(tenantContext));Best practices
Section titled “Best practices”- Keep resolvers deterministic within a request or operation
- Provide a safe fallback to the default namespace
- Avoid expensive resolution logic, as it is called frequently
For web applications, see ASP.NET Core namespace resolution.