MSQLite.Wrapper.Framework 1.0.8

There is a newer version of this package available.
See the version list below for details.
dotnet add package MSQLite.Wrapper.Framework --version 1.0.8
                    
NuGet\Install-Package MSQLite.Wrapper.Framework -Version 1.0.8
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MSQLite.Wrapper.Framework" Version="1.0.8" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MSQLite.Wrapper.Framework" Version="1.0.8" />
                    
Directory.Packages.props
<PackageReference Include="MSQLite.Wrapper.Framework" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MSQLite.Wrapper.Framework --version 1.0.8
                    
#r "nuget: MSQLite.Wrapper.Framework, 1.0.8"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package MSQLite.Wrapper.Framework@1.0.8
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=MSQLite.Wrapper.Framework&version=1.0.8
                    
Install as a Cake Addin
#tool nuget:?package=MSQLite.Wrapper.Framework&version=1.0.8
                    
Install as a Cake Tool

MSQLite.Wrapper

A high-performance, zero-dependency C++/CLI wrapper for SQLite that provides both powerful low-level control and convenient high-level ORM features.

This library is designed to be a fast, efficient, and easy-to-use bridge between your .NET application and the power of SQLite, without requiring any external dependencies.

Features

  • Zero Dependencies: The library is self-contained. It includes the SQLite source and does not require you to ship any extra files.
  • High Performance: Built with C++/CLI to minimize overhead between the managed (.NET) and native (SQLite) worlds.
  • Cross-Platform Support: Targets both .NET Framework 4.6.1+ and .NET Core 3.1+ (including .NET 6, 7, 8 and beyond) for both x86 and x64 architectures.
  • Rich ORM-like Features: Includes methods like InsertReturning, UpdateReturning, and UpsertReturning that work directly with your C# objects.
  • Full Low-Level Control: Provides access to prepared Statement objects for fine-grained control over parameter binding and result iteration.
  • Advanced Functionality: Supports transactions, savepoints, incremental BLOB I/O for large data, and database backup capabilities.
  • Fully Documented: All public methods include XML comments for IntelliSense support in Visual Studio.

Installation

Install the package from NuGet.

Below is the code of the test program, which demonstrates all major features in a practical context.

using MSQLite;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

// A console application to test all features of the MSQLite library.
// Each major feature is tested in a separate method for clarity.
// The application creates a temporary database, runs the tests, and deletes it upon completion.
public class Program
{
    // Define a test model to verify ORM-like features.
    // The properties represent various data types supported by the library.
    public class User
    {
        // By convention, the "Id" property will be treated as the auto-incrementing primary key.
        public long Id { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public double Score { get; set; }
        public DateTime CreatedAt { get; set; }
        public bool IsActive { get; set; }
        public int? NullableInt { get; set; }
        public byte[] ProfilePicture { get; set; }

        public override string ToString()
        {
            return $"Id: {Id}, Name: {Name}, Email: {Email}, IsActive: {IsActive}, CreatedAt: {CreatedAt:O}, NullableInt: {NullableInt?.ToString() ?? "NULL"}";
        }
    }

    // Paths for the database files.
    private const string DbFile = "msqlite_test.db";
    private const string BackupFile = "msqlite_backup.db";

    public static void Main(string[] args)
    {
        // Pre-cleanup in case a previous run failed.
        File.Delete(DbFile);
        File.Delete(BackupFile);

        Console.WriteLine("--- Starting Test Suite for MSQLite Library ---");
        var stopwatch = Stopwatch.StartNew();

        try
        {
            // The main method that launches all tests.
            RunAllTests();
        }
        catch (Exception ex)
        {
            // In case of failure, print detailed error information.
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine($"\n!!! TEST FAILED with unhandled exception: {ex.Message}");
            Console.WriteLine(ex.StackTrace);
            Console.ResetColor();
        }
        finally
        {
            // Final cleanup after all tests are done.
            File.Delete(DbFile);
            File.Delete(BackupFile);
            stopwatch.Stop();
            Console.WriteLine($"\n--- Test Suite Finished. Execution time: {stopwatch.ElapsedMilliseconds} ms. Cleanup complete. ---");
        }
    }

    /// <summary>
    /// The main test runner. Creates a DB connection and sequentially calls all test methods.
    /// </summary>
    private static void RunAllTests()
    {
        // All tests are executed within a single connection.
        using (var db = new SQLite(DbFile))
        {
            Console.WriteLine($"Database '{DbFile}' opened successfully.");

            // Call test methods in a logical order.
            TestBasicExecutionAndCrud(db);
            TestOrmFeatures(db);
            TestIterationFeatures(db);
            TestBlobHandling(db);
            TestTransactionsAndSavepoints(db);
            TestSchemaAndGeneration(db);
            TestErrorHandling(db);
            TestBackup(db);
        }
        Console.WriteLine($"Database '{DbFile}' closed.");
    }

    /// <summary>
    /// Tests basic operations: SQL execution, CRUD via Statement, and scalar queries.
    /// </summary>
    private static void TestBasicExecutionAndCrud(SQLite db)
    {
        RunTest(nameof(TestBasicExecutionAndCrud), () =>
        {
            // 1. Create a table using a simple Execute call.
            db.Execute("CREATE TABLE Logs (Id INTEGER PRIMARY KEY, Message TEXT, Timestamp INTEGER)");
            Assert(db.GetTableList().Rows.Any(r => r == "Logs"), "The 'Logs' table should be created.");

            // 2. Use CreateStatement to insert data with parameters.
            using (var stmt = db.CreateStatement("INSERT INTO Logs (Message, Timestamp) VALUES (@msg, @ts)"))
            {
                stmt.Bind("@msg", "System started");
                stmt.Bind("@ts", DateTimeOffset.UtcNow.ToUnixTimeSeconds());
                stmt.StepWithRetry(); // Execute a step to perform the insertion.
            }

            // 3. Use ExecuteScalar to check the record count.
            int count = db.ExecuteScalar<int>("SELECT COUNT(*) FROM Logs");
            Assert(count == 1, "There should be one record in the Logs table.");

            // 4. Read and verify the inserted data.
            using (var stmt = db.CreateStatement("SELECT Message FROM Logs WHERE Id = 1"))
            {
                Assert(stmt.StepWithRetry(), "A record with Id=1 should be found.");
                string message = (string)stmt.GetColumnValue(0);
                Assert(message == "System started", "The log message should match.");
            }

            // 5. Update data.
            db.Execute("UPDATE Logs SET Message = 'System updated' WHERE Id = 1");
            string updatedMessage = db.ExecuteScalar<string>("SELECT Message FROM Logs WHERE Id = 1");
            Assert(updatedMessage == "System updated", "The message should be updated.");

            // 6. Delete data.
            db.Execute("DELETE FROM Logs WHERE Id = 1");
            count = db.ExecuteScalar<int>("SELECT COUNT(*) FROM Logs");
            Assert(count == 0, "The record should be deleted.");
        });
    }

    /// <summary>
    /// Tests high-level ORM-like features: Insert, Update, Delete, Upsert, Exists.
    /// </summary>
    private static void TestOrmFeatures(SQLite db)
    {
        RunTest(nameof(TestOrmFeatures), () =>
        {
            // 1. Generate SQL to create a table based on a C# class and then execute it.
            string createSql = db.GenerateCreateTableSql<User>("Users");
            db.Execute(createSql);
            Assert(db.GetTableList().Rows.Any(r => r == "Users"), "The 'Users' table should be created.");

            // 2. Create a test object.
            var alice = new User { Name = "Alice", Email = "alice@example.com", Score = 95.5, CreatedAt = DateTime.UtcNow, IsActive = true, NullableInt = 100 };

            // 3. Test InsertReturning, which inserts an object and returns it with the populated ID.
            var insertedAlice = db.InsertReturning("Users", alice);
            Assert(insertedAlice.Id > 0, "The returned object should have a generated Id.");
            Assert(insertedAlice.Name == alice.Name, "Name should match after InsertReturning.");
            Console.WriteLine($"  - InsertReturning returned user: {insertedAlice}");

            // 4. Test Exists to check for the record's presence.
            Assert(db.Exists("Users", insertedAlice.Id), "User with the Id should exist.");

            // 5. Test UpdateReturning.
            insertedAlice.Name = "Alice Smith";
            var updatedAlice = db.UpdateReturning("Users", insertedAlice);
            Assert(updatedAlice.Name == "Alice Smith", "Name should be updated after UpdateReturning.");

            // 6. Test UpsertReturning (in update mode).
            updatedAlice.Score = 99.0;
            var upsertedAlice = db.UpsertReturning("Users", updatedAlice);
            Assert(upsertedAlice.Score == 99.0, "Score should be updated after UpsertReturning (Update).");

            // 7. Test UpsertReturning (in insert mode).
            var bob = new User { Name = "Bob", Email = "bob@example.com", CreatedAt = DateTime.UtcNow, IsActive = false };
            var upsertedBob = db.UpsertReturning("Users", bob);
            Assert(upsertedBob.Id > 0, "Bob should have a generated Id after UpsertReturning (Insert).");
            Assert(db.Exists("Users", upsertedBob.Id), "Bob should exist in the DB.");

            // 8. Test Delete by primary key.
            db.Delete("Users", insertedAlice.Id);
            Assert(!db.Exists("Users", insertedAlice.Id), "Alice should be deleted.");

            // 9. Test Delete by dictionary (WHERE clause).
            db.Delete("Users", new Dictionary<string, object> { { "Name", "Bob" } });
            Assert(!db.Exists("Users", upsertedBob.Id), "Bob should be deleted by name.");
        });
    }

    /// <summary>
    /// A helper method to run tests, print status, and catch specific test exceptions.
    /// </summary>
    private static void RunTest(string testName, Action testAction)
    {
        Console.Write($"\nRunning test: {testName}... ");
        try
        {
            testAction();
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("PASSED");
            Console.ResetColor();
        }
        catch (Exception ex)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine($"FAILED\n  - Reason: {ex.Message}");
            Console.ResetColor();
            throw; // Re-throw to stop the entire test suite on failure.
        }
    }

    /// <summary>
    /// A simple assertion method. Throws an exception if the condition is false.
    /// </summary>
    private static void Assert(bool condition, string message)
    {
        if (!condition)
        {
            throw new Exception($"Assertion failed: {message}");
        }
    }
}
Product Compatible and additional computed target framework versions.
.NET Framework net461 is compatible.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 0 10/11/2025
1.0.15 161 10/2/2025
1.0.14 156 10/1/2025
1.0.13 153 9/30/2025
1.0.12 157 9/29/2025
1.0.11 148 9/26/2025
1.0.10 161 9/24/2025
1.0.9 328 9/24/2025
1.0.8 149 9/23/2025
1.0.7 345 9/20/2025

Initial public release of MSQLite.Wrapper.Framework targeting .NET Framework 4.6.1+.

Highlights:
- C++/CLI wrapper around SQLite with managed API for .NET Framework.
- x86 and x64 runtime support with reference assemblies for compatibility.
- Type-safe ExecuteScalar<T> using ConvertTo<T> for reliable value conversion.
- Full XML documentation for public methods, including encoding-aware BindText overloads.
- Integrated encryption support via SQLite3 Multiple Ciphers (AES, ChaCha20, etc.).
- Clean packaging layout with ref/lib separation and PDBs for debugging.