Docs
Tenantry CoreAPI reference

TenantryTenantBuilderExtensions class

Namespace: Microsoft.Extensions.DependencyInjection · Package: Tenantry.Core · API reference

Tenantry's core features on ITenantBuilder<TKey>: the tenant store, its cache and per-tenant connection strings.

public static class TenantryTenantBuilderExtensions

Methods

CacheTenants<TKey>(ITenantBuilder<TKey>, Action<TenantStoreCacheOptions>?)

Caches the tenants Tenantry reads from the tenant store, so a request does not ask the store for its tenant each time. ITenantStoreCache<TKey> then removes a tenant that changes (AddTenantry always registers it, so code that invalidates runs with caching off too).

public static ITenantBuilder<TKey> CacheTenants<TKey>(this ITenantBuilder<TKey> builder, Action<TenantStoreCacheOptions>? configure = null) where TKey : IEquatable<TKey>, IParsable<TKey>

Type parameters:

  • TKey: The tenant identifier type.

Parameters:

  • builder ITenantBuilder<TKey>: The tenant builder.
  • configure Action<TenantStoreCacheOptions>: Sets how long a tenant is cached, or null for the default (5 minutes).

Returns: ITenantBuilder<TKey>: The same builder for chaining.

Exceptions:

The cache serves Tenantry's own lookups: app.UseTenantry()'s, and ITenantLookup<TKey>'s, which ITenantScopeFactory<TKey>.RunInScopeAsync and background work use. It keeps each tenant the store finds, by the id or identifier it was looked up with, in memory for TenantStoreCacheOptions.Duration. A lookup that finds no tenant is not cached, so a tenant added to the store is found at once; ITenantStore<TKey>.GetAllTenantsAsync is never cached. Code that injects ITenantStore<TKey> reads the store itself.

A tenant that changes (is suspended, say, which an access validator reads) is served as it was until its entry expires: call ITenantStoreCache<TKey>.Invalidate when you change it. Each instance of the application has its own cache. Calling it again configures the same options. It reads the time from a registered TimeProvider, if there is one.

builder.Services.AddTenantry<Guid>(tenant => tenant
    .ResolveFromSubdomain()
    .UseStore<AppTenantStore>()
    .CacheTenants(o => o.Duration = TimeSpan.FromMinutes(1)));

UseConnectionStrings<TKey>(ITenantBuilder<TKey>, Action<TenantConnectionStringOptions<TKey>>)

Configures how each tenant's connection string is found, and registers ITenantConnectionStringProvider<TKey> and CurrentTenantConnectionString<TKey> as singletons.

public static ITenantBuilder<TKey> UseConnectionStrings<TKey>(this ITenantBuilder<TKey> builder, Action<TenantConnectionStringOptions<TKey>> configure) where TKey : IEquatable<TKey>, IParsable<TKey>

Type parameters:

  • TKey: The tenant identifier type.

Parameters:

  • builder ITenantBuilder<TKey>: The tenant builder.
  • configure Action<TenantConnectionStringOptions<TKey>>: Sets the delegates that return a tenant's connection string.

Returns: ITenantBuilder<TKey>: The same builder for chaining.

Exceptions:

  • InvalidOperationException: Neither delegate is set after configure runs.

Calling it again configures the same options instance, so a later call can replace a delegate.

builder.Services.AddTenantry<string>(tenant => tenant
    .ResolveFromHeader("X-Tenant-Id")
    .UseStore<AppTenantStore>()
    .UseConnectionStrings(options =>
        options.GetConnectionString = t => $"Server=db;Database=app_{t.TenantId};Integrated Security=true"));

builder.Services.AddDbContext<AppDbContext>((sp, options) =>     options.UseSqlServer(sp.GetRequiredService<CurrentTenantConnectionString<string>>().Get())); ```

### `UseInMemoryStore<TKey>(ITenantBuilder<TKey>, IEnumerable<ITenantDescriptor<TKey>>)`

Registers a pre-populated in-memory tenant store. Suitable for testing and simple single-instance deployments.

```csharp
public static ITenantBuilder<TKey> UseInMemoryStore<TKey>(this ITenantBuilder<TKey> builder, IEnumerable<ITenantDescriptor<TKey>> tenants) where TKey : IEquatable<TKey>, IParsable<TKey>

Type parameters:

  • TKey: The tenant identifier type.

Parameters:

  • builder ITenantBuilder<TKey>: The tenant builder.
  • tenants IEnumerable<ITenantDescriptor<TKey>>: The tenants the store holds. The store does not change after registration.

Returns: ITenantBuilder<TKey>: The same builder for chaining.

Exceptions:

  • InvalidOperationException: A tenant store is already registered.

UseStore<TKey>(ITenantBuilder<TKey>, Func<IServiceProvider, ITenantStore<TKey>>)

Registers a custom ITenantStore<TKey> implementation with a factory function.

public static ITenantBuilder<TKey> UseStore<TKey>(this ITenantBuilder<TKey> builder, Func<IServiceProvider, ITenantStore<TKey>> factory) where TKey : IEquatable<TKey>, IParsable<TKey>

Type parameters:

  • TKey: The tenant identifier type.

Parameters:

  • builder ITenantBuilder<TKey>: The tenant builder.
  • factory Func<IServiceProvider, ITenantStore<TKey>>: Creates the store from the scope's services.

Returns: ITenantBuilder<TKey>: The same builder for chaining.

Exceptions:

  • InvalidOperationException: A tenant store is already registered.

The store is registered with a scoped lifetime and is resolved per operation, so the factory may return an instance that depends on scoped services such as a DbContext.

On this page