Skip to content

Configuration

Tom Laird-McConnell edited this page May 24, 2026 · 1 revision

Configuration

LottaDB configuration is split into two levels: catalog-level (shared infrastructure) and database-level (type registrations and handlers).

Storage Providers

Storage is configured using Use*() extension methods. Each method sets up all three storage concerns -- table client, blob client, and Lucene directory -- in one call.

UseAzure (production) -- built into LottaDB

dotnet add package LottaDB
var catalog = new LottaCatalog("myapp", catalog => catalog.UseAzure(connectionString));

Configures TableServiceClient and BlobServiceClient from the connection string. Lucene uses AzureDirectory (index persisted to blob storage).

A shorthand connection string constructor is also available:

// Equivalent to UseAzure(connectionString)
var catalog = new LottaCatalog("myapp", connectionString);

UseMemory (testing) -- requires LottaDB.Memory

dotnet add package LottaDB.Memory
var catalog = new LottaCatalog("myapp", catalog => catalog.UseMemory());

Configures MemoryTableServiceClient, MemoryBlobServiceClient, and RAMDirectory. All data lives in memory -- fast, no I/O, no cleanup. Ideal for unit tests.

UseFileSystem (local dev) -- requires LottaDB.FileSystem

dotnet add package LottaDB.FileSystem
var catalog = new LottaCatalog("myapp", catalog => catalog.UseFileSystem(@"C:\data\myapp"));

Configures FileTableServiceClient, FileBlobServiceClient, and FSDirectory. Data is persisted as files on disk under the specified root path. Good for local development and debugging test failures.

UseSQLite (local dev) -- requires LottaDB.SQLite

dotnet add package LottaDB.SQLite
var catalog = new LottaCatalog("myapp", catalog => catalog.UseSQLite(@"C:\data"));

Configures SqliteTableServiceClient, SqliteBlobServiceClient, and FSDirectory. Table and blob data stored in a SQLite database file; Lucene index stored on disk. Good balance of speed and persistence.

Combining providers with other settings

The Use*() methods can be combined with other catalog-level settings in the same configure callback:

var catalog = new LottaCatalog("myapp", catalog =>
{
    catalog.UseAzure(connectionString);
    catalog.Analyzer = new StandardAnalyzer(LuceneVersion.LUCENE_48);
    catalog.EmbeddingGenerator = myEmbeddingGenerator;
});

Catalog-level properties

These are internal and can only be set through the constructor's configure callback:

Property Type Default Description
Analyzer Analyzer EnglishAnalyzer Lucene analyzer for text tokenization. Shared across all databases in the catalog.
EmbeddingGenerator IEmbeddingGenerator<string, Embedding<float>>? null (disabled) Embedding generator for Vector Search.

Database configuration

Configure databases via GetDatabaseAsync:

var db = await catalog.GetDatabaseAsync("social", config =>
{
    config.Store<Actor>();
    config.Store<Note>();
    config.On<Note>(async (note, kind, db, ct) =>
    {
        // trigger logic
    });
});

Store() -- register a type

Register a type with default settings (AutoQueryable on, ULID key auto-generated):

config.Store<Actor>();

With fluent configuration:

config.Store<Note>(s =>
{
    s.SetKey(n => n.NoteId);
    s.AddQueryable(n => n.AuthorId).NotAnalyzed();
    s.AddQueryable(n => n.Content);
    s.DefaultSearch(n => n.Content);
});

See Storing POCOs for the full fluent API.

On() -- register handlers

Handlers run inline after every save or delete:

config.On<Note>(async (note, kind, db, ct) =>
{
    if (kind == TriggerKind.Saved)
        await db.SaveAsync(new NoteView { ... }, ct);
});

See Triggers and Views for materialized views and cascading handlers.

OnUpload() -- blob metadata extraction

Enable automatic metadata extraction when blobs are uploaded:

config.OnUpload();  // default handler: MIME detection, text extraction

Or provide a custom handler:

config.OnUpload(async (path, contentType, content, db, ct) =>
{
    // custom processing
    return new BlobFile { Path = path, ContentType = contentType };
});

See Blob Storage for details.

AutoQueryable

AutoQueryable is on by default. It promotes all simple-type properties to queryable columns. To disable for a specific type:

config.Store<Note>(s =>
{
    s.AutoQueryable(false);
    s.AddQueryable(n => n.AuthorId).NotAnalyzed();
    s.AddQueryable(n => n.Content);
});

ILottaConfiguration properties

Property Type Default Description
AutoCommitDelay int (framework default) Interval in milliseconds for automatic Lucene search commits
AutoKeyProperties string[] id, _id, key, _key, pk, primaryKey, uuid, guid Convention-based key property names for auto-detection. First match wins (case-insensitive).

Full example

var catalog = new LottaCatalog("tenant123", catalog =>
{
    catalog.UseAzure(connectionString);
    catalog.EmbeddingGenerator = new OllamaEmbeddingGenerator(...);
});

var db = await catalog.GetDatabaseAsync("notes", config =>
{
    config.Store<Note>(s =>
    {
        s.SetKey(n => n.NoteId);
        s.AddQueryable(n => n.Content).Vector();
        s.DefaultSearch(n => n.Content);
    });

    config.Store<NoteView>();

    config.On<Note>(async (note, kind, db, ct) =>
    {
        if (kind == TriggerKind.Deleted)
        {
            await db.DeleteManyAsync<NoteView>(nv => nv.NoteId == note.NoteId, ct);
            return;
        }
        await db.SaveAsync(new NoteView
        {
            Id = $"nv-{note.NoteId}",
            NoteId = note.NoteId,
            Content = note.Content,
        }, ct);
    });

    config.OnUpload();
});

Clone this wiki locally