Lightning.NET Documentation

repository·main·Indexed 19 days ago

https://github.com/coreykaylor/lightning.net

A high-performance .NET wrapper for the Lightning Memory-Mapped Database (LMDB), providing a fast, transactional, and ACID-compliant key-value store. Includes guides on installing the LightningDB NuGet package, performing basic Put/Get operations, handling duplicate keys with cursors, and configuring custom key and duplicate ordering using various comparers.

Tokens
2.4K
Snippets
6
Records
6
Agent score
16%

What's inside Lightning.NET

  1. How to handle multiple values for the same key

    main

    LMDB supports duplicate keys if the database is configured with the DatabaseOpenFlags.DuplicatesSort flag.

    To retrieve these values, you can use a Cursor:

    1. Create a cursor with tx.CreateCursor(db).
    2. Position it at the first occurrence using cursor.Set(key).
    3. Iterate through duplicates using cursor.NextDuplicate() until it returns a resultCode other than MDBResultCode.Success.

    Alternatively, you can use the convenience method cursor.AllValues(key) to get an IEnumerable of all values associated with that key.

    // Configure the database to support duplicate keys
    var dbConfig = new DatabaseConfiguration { Flags = DatabaseOpenFlags.Create | DatabaseOpenFlags.DuplicatesSort };
    
    // ... inside a transaction ...
    using (var db = tx.OpenDatabase(configuration: dbConfig))
    {
        var key = Encoding.UTF8.GetBytes("fruit");
        tx.Put(db, key, Encoding.UTF8.GetBytes("apple"));
        tx.Put(db, key, Encoding.UTF8.GetBytes("cherry"));
        tx.Commit();
    }
    
    // ... retrieval using cursor ...
    using (var cursor = tx.CreateCursor(db))
    {
        var result = cursor.Set(key);
        if(result == MDBResultCode.Success)
        {
            do
            {
                var current = cursor.GetCurrent();
                Console.WriteLine($"{Encoding.UTF8.GetString(current.key.AsSpan())}: {Encoding.UTF8.GetString(current.value.AsSpan())}");
            }
            while (cursor.NextDuplicate().resultCode == MDBResultCode.Success);
        }
    
        // Or simpler:
        var values = cursor.AllValues(key);
        foreach(var value in values)
        {
            Console.WriteLine($"fruit: {Encoding.UTF8.GetString(value.AsSpan())}");
        }
    }
  2. Install LightningDB via NuGet or .NET CLI

    main

    To use Lightning.NET in your project, install the LightningDB NuGet package using either the Package Manager Console or the .NET CLI.

    # Using Package Manager Console
    Install-Package LightningDB
    
    # Using .NET CLI
    dotnet add package LightningDB
  3. Basic Usage: Create an environment and perform Put/Get operations

    main

    To use Lightning.NET, follow these steps:

    1. Create a LightningEnvironment with a specified path and call .Open().
    2. Start a transaction using env.BeginTransaction().
    3. Open a database within that transaction using tx.OpenDatabase(). Use DatabaseOpenFlags.Create in the DatabaseConfiguration to create a new database.
    4. Use tx.Put(db, key, value) to insert data and tx.Commit() to save changes.
    5. To retrieve data, start a transaction (optionally with TransactionBeginFlags.ReadOnly) and use tx.Get(db, key). This returns a tuple containing resultCode, key, and value.
    using System;
    using System.Text;
    using LightningDB;
    
    class Program
    {
        static void Main()
        {
            // Specify the path to the database environment
            using var env = new LightningEnvironment("path_to_your_database");
            env.Open();
    
            // Begin a transaction and open (or create) a database
            using (var tx = env.BeginTransaction())
            using (var db = tx.OpenDatabase(configuration: new DatabaseConfiguration { Flags = DatabaseOpenFlags.Create }))
            {
                // Put a key-value pair into the database
                tx.Put(db, Encoding.UTF8.GetBytes("hello"), Encoding.UTF8.GetBytes("world"));
                tx.Commit();
            }
    
            // Begin a read-only transaction to retrieve the value
            using (var tx = env.BeginTransaction(TransactionBeginFlags.ReadOnly))
            using (var db = tx.OpenDatabase())
            {
                var (resultCode, key, value) = tx.Get(db, Encoding.UTF8.GetBytes("hello"));
                if (resultCode == MDBResultCode.Success)
                {
                    Console.WriteLine($"{Encoding.UTF8.GetString(key)}: {Encoding.UTF8.GetString(value)}");
                }
                else
                {
                    Console.WriteLine("Key not found.");
                }
            }
        }
    }
  4. Configure Docker and Colima for multi-platform LMDB builds

    main

    If you are using Colima with docker-cli instead of Docker Desktop, follow these steps to prepare your environment for multi-platform builds. This setup ensures that all necessary platforms are available for Docker to handle various Linux targets using the --platform flag.

    Steps:

    1. Install Docker and Colima: brew install docker brew install colima
    2. Start Colima using macOS built-in virtualization (vz) and Rosetta for performance: colima start --vm-type=vz --vz-rosetta
    3. Install all available platform support via binfmt to enable multi-platform Docker runs: docker run --privileged --rm tonistiigi/binfmt --install all
    brew install docker
    brew install colima
    colima start --vm-type=vz --vz-rosetta
    docker run --privileged --rm tonistiigi/binfmt --install all
  5. Set up cross-compilation for LMDB on macOS

    main

    To target Windows and Android from a macOS environment, you must install mingw64 and android-ndk build tools using Homebrew. You also need to set the NDK environment variable to point to your Android NDK installation path.

    Prerequisites:

    • macOS
    • Homebrew

    Steps:

    1. Install required tools via brew bundle: brew bundle install
    2. Export the NDK path: export NDK="/opt/homebrew/share/android-ndk"
    brew bundle install
    export NDK="/opt/homebrew/share/android-ndk"
  6. Configure custom key and duplicate ordering

    main

    You can control how keys and duplicate values are sorted using DatabaseConfiguration. This is useful for non-lexicographical sorting (e.g., integers or UTF-8 strings).

    • Use config.CompareWith(comparer) to define how keys are sorted.
    • Use config.FindDuplicatesWith(comparer) to define how duplicate values for the same key are sorted.

    Available comparers in LightningDB.Comparers:

    ComparerDescription
    BitwiseComparerLexicographic byte comparison (default LMDB behavior)
    ReverseBitwiseComparerLexicographic descending
    SignedIntegerComparer4/8-byte signed integers with proper negative ordering
    UnsignedIntegerComparer4/8-byte unsigned integers
    Utf8StringComparerOrdinal UTF-8 string comparison
    LengthComparerSort by length first, then content
    LengthOnlyComparerSort by length only
    HashCodeComparerHash-based comparison for large values

    Note: Reverse variants (e.g., ReverseSignedIntegerComparer) are available for most comparers.

    var config = new DatabaseConfiguration
    {
        Flags = DatabaseOpenFlags.Create | DatabaseOpenFlags.DuplicatesSort
    };
    
    // Sort keys as signed integers (negative values sort before positive)
    config.CompareWith(SignedIntegerComparer.Instance);
    
    // Sort duplicate values in reverse order
    config.FindDuplicatesWith(ReverseBitwiseComparer.Instance);
    
    using var db = tx.OpenDatabase(configuration: config);